You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Digitalisation_EPA_Serveur/EPAServeur/Services/EngagementService.cs

438 lines
17 KiB

using EPAServeur.Context;
using EPAServeur.Exceptions;
using EPAServeur.IServices;
using EPAServeur.Models.EP;
using IO.Swagger.DTO;
using IO.Swagger.Enum;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace EPAServeur.Services
{
public class EngagementService : IEngagementService
{
#region Variables
/// <summary>
/// Accès et gestion de la base de données
/// </summary>
private readonly EpContext epContext;
/// <summary>
/// Accès et service collaborateur
/// </summary>
private readonly ICollaborateurService collaborateurService;
/// <summary>
/// Nombre d'éléments min à afficher par page
/// </summary>
private readonly int minParPage = 5;
/// <summary>
/// Nom d'éléments max à affichar par page
/// </summary>
private readonly int maxParPage = 100;
/// <summary>
/// Nombre d'éléments à afficher par défaut par page
/// </summary>
private readonly int defaultParPage = 15;
/// <summary>
/// Numéro de page min à afficher par défaut
/// </summary>
private readonly int defaultNumPage = 1;
/// <summary>
/// Ordonnancement par défaut
/// </summary>
private readonly bool defaultAsc = true;
#endregion
#region Contructeurs
/// <summary>
/// Constructeur de la classe EngagementService
/// </summary>
/// <param name="_epContext"></param>
public EngagementService(EpContext _epContext, ICollaborateurService _collaborateurService)
{
epContext = _epContext;
collaborateurService = _collaborateurService;
}
#endregion
#region Méthodes Service
/// <summary>
/// Récupérer la liste des engagements de manière asynchrone
/// </summary>
/// <param name="etatsEngagement"></param>
/// <param name="idBUs"></param>
/// <param name="asc"></param>
/// <param name="numPage"></param>
/// <param name="parPage"></param>
/// <param name="texte"></param>
/// <param name="tri"></param>
/// <returns></returns>
public async Task<IEnumerable<EngagementDTO>> GetEngagementsAsync(List<long> idBUs, List<EtatEngagement> etatsEngagement, bool? asc, int? numPage, int? parPage, string texte, string tri)
{
IQueryable<Engagement> query;
IEnumerable<Engagement> engagements;
IEnumerable<EngagementDTO> engagementDTOs;
IEnumerable<CollaborateurDTO> collaborateurDTOs;
query = epContext.Engagement.Include(engagement => engagement.Ep);
query = IdBUsFilter(query, idBUs);
query = EtatsEngagementFilter(query, etatsEngagement);
query = ActionFilter(query, texte);
query = OrderByColumn(query, asc, tri);
query = SkipAndTake(query, parPage, numPage);
engagements = await query.ToListAsync();
collaborateurDTOs = await GetCollaborateurDTOs(engagements);
engagementDTOs = engagements.Select(engagement => GetEngagementDTO(engagement, collaborateurDTOs));
return engagementDTOs;
}
public async Task<long> GetEngagementsCountAsync(List<long> idBUs, List<EtatEngagement> etatsEngagement, bool? asc, int? numPage, int? parPage, string texte, string tri)
{
IQueryable<Engagement> query;
long count;
query = epContext.Engagement.Include(engagement => engagement.Ep);
query = IdBUsFilter(query, idBUs);
query = EtatsEngagementFilter(query, etatsEngagement);
query = ActionFilter(query, texte);
query = OrderByColumn(query, asc, tri);
query = SkipAndTake(query, parPage, numPage);
count = await query.CountAsync();
return count;
}
/// <summary>
/// Donner une réponse à un engagement de manière asynchrone
/// </summary>
/// <param name="engagementDTO"></param>
/// <param name="idEngagement"></param>
/// <returns></returns>
public async Task<EngagementDTO> RepondreEngagementAsync(EngagementDTO engagementDTO, long idEngagement)
{
IEnumerable<CollaborateurDTO> collaborateurDTOs;
Engagement engagement;
IsEngagementValide(engagementDTO);
if (!engagementDTO.Id.HasValue || engagementDTO.Id.Value != idEngagement)
throw new EngagementIncompatibleIdException("L'id de l'engagement à mettre à jour et l'engagement à mettre à jour sont incompatible.");
engagement = await epContext.Engagement.Include(engagement => engagement.Ep).FirstOrDefaultAsync(engagement => engagement.IdEngagement == idEngagement);
if (engagement == null)
throw new EngagementNotFoundException();
collaborateurDTOs = await GetCollaborateurDTOs(engagement);
engagement = SetReponseEngagement(engagement, engagementDTO);
await epContext.SaveChangesAsync();
return GetEngagementDTO(engagement, collaborateurDTOs);
}
#endregion
#region Méthodes Privée
/// <summary>
/// Vérifier si un objet EngagementDTO est valide pour ajout ou mise à jour
/// </summary>
/// <remarks> Un objet EngagementDTO est valide si l'action, le dispositif, la modalité et la date limite n'est pas null, si l'EP est signé, et si l'EP est présent dans la base de données.</remarks>
/// <param name="formation"></param>
/// <exception cref="EPAServeur.Exceptions.EngagementInvalidException"></exception>
private void IsEngagementValide(EngagementDTO engagementDTO)
{
// Vérifier que l'engagement n'est pas null
if (engagementDTO == null)
throw new EngagementInvalidException("Aucun engagement n'a été reçu.");
// Vérfier que l'engagement a bien un EP
if (engagementDTO.Ep == null || !engagementDTO.Ep.Id.HasValue)
throw new EngagementInvalidException("Impossible de répondre à un engagement sans EP.");
// Vérfier que l'ep a bien été signé par le collaborateur
if (engagementDTO.Ep.Statut != StatutEp.Signe)
throw new EngagementInvalidException("Impossible de répondre à un engagement d'un EP qui n'est pas en cours et qui n'a pas été signé par le collaborateur.");
// Vérifier que l'engagement a bien une action
if (string.IsNullOrWhiteSpace(engagementDTO.Action))
throw new EngagementInvalidException("L'action de l'engagement doit contenir au moins 1 caractère.");
// Vérifier que l'engagement a bien un dispositif
if (string.IsNullOrWhiteSpace(engagementDTO.Dispositif))
throw new EngagementInvalidException("Le dispostif de l'engagement doit contenir au moins 1 caractère.");
// Vérifier que l'engagement a bien une modalité
if (string.IsNullOrWhiteSpace(engagementDTO.Modalite))
throw new EngagementInvalidException("La modalité de l'engagement doit contenir au moins 1 caractère.");
// Vérifier que l'engagement a bien une date limite
if (!engagementDTO.DateLimite.HasValue)
throw new EngagementInvalidException("Impossible de répondre à l'engagement sans date limite.");
// Vérifier que l'engagement a bien raison expliquant pourquoi l'engagement n'est pas réalisable lorsque l'état de l'engagement n'est pas réalisable
if (engagementDTO.EtatEngagement == EtatEngagement.NonRealisable && string.IsNullOrWhiteSpace(engagementDTO.RaisonNonRealisable))
throw new EngagementInvalidException("Impossible de répondre à l'engagement, une raison doit être rensignée lorsqu'un engagement n'est pas réalisé.");
// Vérfier que l'EP lié à l'engagement est présent dans la BDD
if (!epContext.Ep.Any(ep => ep.IdEP == engagementDTO.Ep.Id.Value))
throw new EngagementInvalidException("L'EP n'existe pas.");
}
/// <summary>
/// Ajouter un ordonnancement croissant ou décroissant sur colonne
/// </summary>
/// <param name="query"></param>
/// <param name="idStatuts"></param>
/// <returns></returns>
private IQueryable<Engagement> OrderByColumn(IQueryable<Engagement> query, bool? asc, string columnName)
{
if (!asc.HasValue)
asc = defaultAsc;
if (string.IsNullOrWhiteSpace(columnName))
{
if (asc.Value)
return query.OrderBy(p => p.Action);
return query.OrderByDescending(p => p.Action);
}
switch (columnName.ToLower())
{
case "action":
if (asc.Value)
return query.OrderBy(p => p.Action);
return query.OrderByDescending(p => p.Action);
case "dispositif":
if (asc.Value)
return query.OrderBy(p => p.Dispositif);
return query.OrderByDescending(p => p.Dispositif);
case "modalite":
if (asc.Value)
return query.OrderBy(p => p.Modalite);
return query.OrderByDescending(p => p.Modalite);
case "date":
if (asc.Value)
return query.OrderBy(p => p.DateLimite);
return query.OrderByDescending(p => p.DateLimite);
default:
if (asc.Value)
return query.OrderBy(p => p.Action);
return query.OrderByDescending(p => p.Action);
}
}
/// <summary>
/// Ajouter un filtre pour récupérer les engagements en fonction de plusieurs identifiants de Business Unit
/// </summary>
/// <param name="query"></param>
/// <param name="idBUs"></param>
/// <returns></returns>
/// <exception cref="EPAServeur.Exceptions.EngagementInvalidException"></exception>
private IQueryable<Engagement> IdBUsFilter(IQueryable<Engagement> query, List<long> idBUs)
{
if (idBUs == null || idBUs.Count == 0)
throw new EngagementInvalidException("Aucune Business Unit n'a été reçu.");
return query.Where(engagement => idBUs.Contains(engagement.Ep.IdBu));
}
/// <summary>
/// Ajouter un filtre pour récupérer les engagements en fonction de plusieurs états d'engagement
/// </summary>
/// <param name="query"></param>
/// <param name="idBUs"></param>
/// <returns></returns>
private IQueryable<Engagement> EtatsEngagementFilter(IQueryable<Engagement> query, List<EtatEngagement> etatsEngagement)
{
if (etatsEngagement == null || etatsEngagement.Count <= 0)
return query;
return query.Where(engagement => etatsEngagement.Contains(engagement.EtatEngagement));
}
/// <summary>
/// Ajouter un filtre pour récupérer les engagements en fonction d'une action
/// </summary>
/// <param name="query"></param>
/// <param name="intitule"></param>
/// <returns></returns>
private IQueryable<Engagement> ActionFilter(IQueryable<Engagement> query, string action)
{
if (string.IsNullOrWhiteSpace(action))
return query;
return query.Where(engagement => engagement.Action.ToLower().Contains(action.ToLower()));
}
/// <summary>
/// Ajouter une pagination
/// </summary>
/// <param name="query"></param>
/// <param name="parPage"></param>
/// <param name="numPage"></param>
/// <returns></returns>
private IQueryable<Engagement> SkipAndTake(IQueryable<Engagement> query, int? parPage, int? numPage)
{
int skip, take;
if (!parPage.HasValue || parPage.Value < minParPage || parPage.Value > maxParPage)
parPage = defaultParPage;
if (!numPage.HasValue || numPage.Value <= 0)
numPage = defaultNumPage;
skip = (numPage.Value - 1) * parPage.Value;
take = parPage.Value;
return query.Skip(skip).Take(take);
}
#region Object to DTO
/// <summary>
/// Récupère un objet EngagementDTO en fonction d'un objet Engagement et d'une liste de CollaborateurDTO
/// </summary>
/// <param name="engagement"></param>
/// <returns></returns>
private EngagementDTO GetEngagementDTO(Engagement engagement, IEnumerable<CollaborateurDTO> collaborateurDTOs)
{
EngagementDTO engagementDTO = new EngagementDTO()
{
Id = engagement.IdEngagement,
Action = engagement.Action,
DateLimite = engagement.DateLimite,
Dispositif = engagement.Dispositif,
Modalite = engagement.Modalite,
RaisonNonRealisable = engagement.RaisonNonRealisable,
EtatEngagement = engagement.EtatEngagement,
Ep = GetEpInformationDTO(engagement.Ep, collaborateurDTOs)
};
return engagementDTO;
}
/// <summary>
/// Récuperer une liste de CollaborateurDTO contenant les collaborateurs et les référents. Retourne null si l'engagement est null.
/// </summary>
/// <param name="typeFormation"></param>
/// <returns></returns>
private async Task<IEnumerable<CollaborateurDTO>> GetCollaborateurDTOs(Engagement engagement)
{
List<Guid?> guids = new List<Guid?>();
guids.Add((Guid?)engagement.Ep.IdCollaborateur);
guids.Add(engagement.Ep.IdReferent);
return await collaborateurService.GetCollaborateurDTOsAsync(guids); ;
}
/// <summary>
/// Récuperer une liste de CollaborateurDTO contenant les collaborateurs et les référents. Retourne null s'il n'y a aucun engagement.
/// </summary>
/// <param name="typeFormation"></param>
/// <returns></returns>
private async Task<IEnumerable<CollaborateurDTO>> GetCollaborateurDTOs(IEnumerable<Engagement> engagements)
{
if (!engagements.Any())
return null;
List<Guid?> guids = engagements.SelectMany(engagement => new[] { (Guid?)engagement.Ep.IdCollaborateur, engagement.Ep.IdReferent }).ToList();
return await collaborateurService.GetCollaborateurDTOsAsync(guids);
}
/// <summary>
/// Récupère un objet EpInformationDTO en fonction d'un objet Ep et d'une liste de CollaborateurDTO
/// </summary>
/// <param name="ep"></param>
/// <returns></returns>
private EpInformationDTO GetEpInformationDTO(Ep ep, IEnumerable<CollaborateurDTO> collaborateurDTOs)
{
CollaborateurDTO collaborateur;
CollaborateurDTO referent;
collaborateur = collaborateurDTOs.FirstOrDefault(collaborateurDTO => collaborateurDTO.Id == ep.IdCollaborateur);
referent = collaborateurDTOs.FirstOrDefault(collaborateurDTO => collaborateurDTO.Id == ep.IdReferent);
EpInformationDTO epInformationDTO = new EpInformationDTO()
{
Id = ep.IdEP,
Type = ep.TypeEP,
Statut = ep.Statut,
DateDisponibilite = ep.DateDisponibilite,
DatePrevisionnelle = ep.DatePrevisionnelle,
Obligatoire = ep.Obligatoire,
Collaborateur = collaborateur,
Referent = referent,
};
return epInformationDTO;
}
#endregion
#region DTO to Object
/// <summary>
/// Modifie la réponse d'un objet Engagement en fonction d'un objet EngagementDTO
/// </summary>
/// <param name="engagement"></param>
/// <param name="engagementDTO"></param>
/// <returns></returns>
private Engagement SetReponseEngagement(Engagement engagement, EngagementDTO engagementDTO)
{
engagement.EtatEngagement = engagementDTO.EtatEngagement;
switch (engagement.EtatEngagement)
{
case EtatEngagement.NonRealisable:
engagement.RaisonNonRealisable = engagementDTO.RaisonNonRealisable;
break;
case EtatEngagement.DateLimitePassee:
engagement.RaisonNonRealisable = "La date limite pour respecter l'engagement est passée.";
break;
default:
engagement.RaisonNonRealisable = null;
break;
}
return engagement;
}
#endregion
#endregion
}
}