using EPAServeur.Context; using EPAServeur.Exceptions; using EPAServeur.IServices; using EPAServeur.Models.EP; using EPAServeur.Models.Formation; using EPAServeur.Models.SaisieChamp; 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 DemandeFormationService : IDemandeFormationService { #region Variables /// /// Accès et gestion de la base de données /// private readonly EpContext epContext; /// /// Accès au service collaborateur /// private readonly ICollaborateurService collaborateurService; /// /// Accès au service permettant de transformer un modèle en dto /// private readonly ITransformDTO transformDTO; /// /// Nombre d'éléments min à afficher par page /// private readonly int minParPage = 5; /// /// Nom d'éléments max à affichar par page /// private readonly int maxParPage = 100; /// /// Nombre d'éléments à afficher par défaut par page /// private readonly int defaultParPage = 15; /// /// Numéro de page min à afficher par défaut /// private readonly int defaultNumPage = 1; /// /// Ordonnancement par défaut /// private readonly bool defaultAsc = true; #endregion #region Contructeurs /// /// Constructeur de la classe FormationService /// /// public DemandeFormationService(EpContext _epContext, ICollaborateurService _collaborateurService, ITransformDTO _transformDTO) { epContext = _epContext; collaborateurService = _collaborateurService; transformDTO = _transformDTO; } #endregion #region Méthodes Service /// /// Récupérer la liste des origines des demandes de formation. /// /// public async Task> GetOriginesDemandeFormationAsync() { IEnumerable origineDemandes; IEnumerable origineDemandeDTOs; origineDemandes = await epContext.OrigineDemandeFormation.ToListAsync(); origineDemandeDTOs = origineDemandes.Select(origineFormation => transformDTO.GetOrigineDemandeFormationDTO(origineFormation)); return origineDemandeDTOs; } /// /// Récupérer la liste des demandes de formation. /// /// Liste des états des demandes à afficher /// liste des ids des BU auxquelles les données sont rattachées /// Indique si les données sont récupérées dans l'ordre croissant ou non /// Numéro de la page du tableau à afficher /// Nombre d’élément maximum à afficher dans le tableau /// Texte permettant de filtrer les données /// Colonne du tableau sur lequel le tri devra être effectué /// Date à partir de laquelle les données son récupérées /// Date jusqu'à laquelle les données sont récupérées /// public async Task> GetDemandesFormationAsync(List etatsDemande, List idBUs, bool? asc, int? numPage, int? parPage, string texte, string tri, DateTime? dateDebut, DateTime? dateFin) { IQueryable query; IEnumerable demandeFormations; IEnumerable demandeFormationDTOs; IEnumerable collaborateurDTOs; query = epContext.DemandeFormation .Include(demandeFormation => demandeFormation.Ep) .Include(demandeFormation => demandeFormation.OrigineDemande) .Include(demandeFormation => demandeFormation.ParticipationFormation) .ThenInclude(participationFormation => participationFormation.Formation); query = StatutEpFilter(query); query = EtatsDemandeFilter(query, etatsDemande); query = IdBUsFilter(query, idBUs); query = DateFilter(query, dateDebut, dateFin); query = SkipAndTake(query, parPage, numPage); demandeFormations = await query.ToListAsync(); collaborateurDTOs = await collaborateurService.GetCollaborateurDTOsAsync(demandeFormations); demandeFormationDTOs = demandeFormations.Select(demandeFormation => transformDTO.GetDemandeFormationDTO(demandeFormation, collaborateurDTOs)); demandeFormationDTOs = CollaborateurFilter(demandeFormationDTOs, texte); demandeFormationDTOs = OrderByColumn(demandeFormationDTOs, asc, tri); return demandeFormationDTOs; } /// /// Récupérer le nombre total de demandes de formation. /// /// Liste des états des demandes à afficher /// liste des ids des BU auxquelles les données sont rattachées /// Texte permettant de filtrer les données /// Date à partir de laquelle les données son récupérées /// Date jusqu'à laquelle les données sont récupérées /// public async Task GetDemandesFormationCountAsync(List etatsDemande, List idBUs, string texte, DateTime? dateDebut, DateTime? dateFin) { IQueryable query; IEnumerable demandeFormations; IEnumerable demandeFormationDTOs; IEnumerable collaborateurDTOs; long count; query = epContext.DemandeFormation .Include(demandeFormation => demandeFormation.Ep) .Include(demandeFormation => demandeFormation.ParticipationFormation) .ThenInclude(participationFormation => participationFormation.Formation); query = StatutEpFilter(query); query = EtatsDemandeFilter(query, etatsDemande); query = IdBUsFilter(query, idBUs); query = DateFilter(query, dateDebut, dateFin); demandeFormations = await query.ToListAsync(); collaborateurDTOs = await collaborateurService.GetCollaborateurDTOsAsync(demandeFormations); demandeFormationDTOs = demandeFormations.Select(demandeFormation => transformDTO.GetDemandeFormationDTO(demandeFormation, collaborateurDTOs)); demandeFormationDTOs = CollaborateurFilter(demandeFormationDTOs, texte); count = demandeFormationDTOs.Count(); return count; } /// /// Créer une demande de formation pour un collaborateur. /// /// /// /// public async Task AddDemandeFormationAsync(DemandeFormationDTO demandeFormationDTO) { IsDemandeFormationValide(demandeFormationDTO); if (demandeFormationDTO.EtatDemande != EtatDemande.EnAttente) throw new DemandeFormationInvalidException("Impossible de créer une demande de formation qui n'est pas en attente."); string collaborateur = string.Format("{0} {1}", demandeFormationDTO.Collaborateur.Nom, demandeFormationDTO.Collaborateur.Prenom); DemandeFormation demandeFormation = transformDTO.SetDemandeFormationWithoutParticipationFormationAndEp(new DemandeFormation(), demandeFormationDTO); IEnumerable statutsEp = Enum.GetValues(typeof(StatutEp)).Cast().Where(statut => statut == StatutEp.Cree || EstEpEnCours(statut)); Ep ep = await epContext.Ep.Include(ep => ep.DemandesFormation) .Where(ep => ep.IdCollaborateur == demandeFormationDTO.Collaborateur.Id && statutsEp.Contains(ep.Statut)) .OrderBy(ep => ep.DateDisponibilite).FirstOrDefaultAsync(); if (ep == null) throw new DemandeFormationInvalidException(string.Format("Il n'existe aucun EP en cours ou créé pour le collaborateur {0}.", collaborateur)); ep.DemandesFormation.Add(demandeFormation); await epContext.SaveChangesAsync(); demandeFormationDTO.Id = demandeFormation.IdDemandeFormation; return demandeFormationDTO; } /// /// Répondre à une demande de formation. /// /// /// /// /// /// public async Task UpdateDemandeFormationAsync(long idDemandeFormation, DemandeFormationDTO demandeFormationDTO) { IsDemandeFormationValide(demandeFormationDTO); if (!demandeFormationDTO.Id.HasValue || demandeFormationDTO.Id.Value != idDemandeFormation) throw new DemandeFormationIncompatibleIdException("La demande de formation ne correspond pas avec l'identifiant reçu."); switch (demandeFormationDTO.EtatDemande) { case EtatDemande.EnAttente: throw new DemandeFormationInvalidException("La demande ne peut pas être mise à jour si aucune réponse n'a été donnée."); case EtatDemande.Validee: demandeFormationDTO = await AccepterDemandeFormation(idDemandeFormation, demandeFormationDTO); break; case EtatDemande.Rejetee: demandeFormationDTO = await RefuserDemandeFormation(idDemandeFormation, demandeFormationDTO); break; } return demandeFormationDTO; } /// /// Supprimer une demande de formation. /// /// /// public async Task DeleteDemandeFormationAsync(long idDemandeFormation) { IEnumerable statutsEp = Enum.GetValues(typeof(StatutEp)).Cast().Where(statut => statut == StatutEp.Cree || EstEpEnCours(statut)); DemandeFormation demandeFormation = await epContext.DemandeFormation.Include(demandeFormation => demandeFormation.Ep) .FirstOrDefaultAsync(demandeFormation => demandeFormation.IdDemandeFormation == idDemandeFormation); if (demandeFormation == null) throw new DemandeFormationNotFoundException("Aucune demande de formation n'a été trouvée."); if (!statutsEp.Contains(demandeFormation.Ep.Statut)) throw new DemandeFormationInvalidException(string.Format("L'EP {1} qui est rattaché à la demande de formation {0} n'est ni créé ni en cours. Statut de l'EP {1}: {2}.", demandeFormation.IdDemandeFormation, demandeFormation.Ep.IdEP, demandeFormation.Ep.Statut)); epContext.Remove(demandeFormation); await epContext.SaveChangesAsync(); return true; } #endregion #region Méthodes Privée /// /// Accepter une demande de formation. /// /// Créer une participation formation et associe cette dernière la demande de formation /// /// /// /// /// private async Task AccepterDemandeFormation(long idDemandeFormation, DemandeFormationDTO demandeFormationDTO) { // Vérifier que la demande de formation a bien une formation if (demandeFormationDTO.Formation == null || !demandeFormationDTO.Formation.Id.HasValue) throw new DemandeFormationInvalidException("Une formation est requise pour accepter une demande de formation."); DemandeFormation demandeFormation = await epContext.DemandeFormation.Include(d => d.ParticipationFormation) .Include(d => d.Ep) .FirstOrDefaultAsync(d => d.IdDemandeFormation == idDemandeFormation); if (demandeFormation == null) throw new DemandeFormationNotFoundException("Aucune demande de formation n'a été trouvée."); Guid idCollaborateur = demandeFormation.Ep.IdCollaborateur; // devra être utilisé pour notifier le collaborateur DateTime dateNow = DateTime.Now; Formation formation = transformDTO.GetFormation(demandeFormationDTO.Formation); ParticipationFormation participationFormation = new ParticipationFormation { DateCreation = dateNow, Formation = formation }; demandeFormation.Etat = demandeFormationDTO.EtatDemande; demandeFormation.DateDerniereReponse = dateNow; demandeFormation.ParticipationFormation = participationFormation; await epContext.SaveChangesAsync(); int nbParticipations = await epContext.ParticipationFormation.Include(p => p.DemandeFormation).Where(p => p.Formation.IdFormation == formation.IdFormation).CountAsync(); demandeFormationDTO.EtatDemande = demandeFormation.Etat; demandeFormationDTO.DateDerniereReponse = demandeFormation.DateDerniereReponse; demandeFormationDTO.Formation.NbParticipations = nbParticipations; return demandeFormationDTO; } /// /// Refuser une demande de formation. /// /// Supprime la participation formation qui est liée à la demande de formation /// /// /// /// /// private async Task RefuserDemandeFormation(long idDemandeFormation, DemandeFormationDTO demandeFormationDTO) { // Vérifier que la demande de formation a bien un commentaire expliquant la raison pour laquelle la demande a été refusée if (string.IsNullOrWhiteSpace(demandeFormationDTO.CommentaireRefus)) throw new DemandeFormationInvalidException("Un commentaire expliquant la raison pour laquelle la demande a été refusée est requis."); DemandeFormation demandeFormation = await epContext.DemandeFormation.Include(d => d.ParticipationFormation) .Include(d => d.Ep) .FirstOrDefaultAsync(d => d.IdDemandeFormation == idDemandeFormation); if (demandeFormation == null) throw new DemandeFormationNotFoundException("Aucune demande de formation n'a été trouvée."); Guid idCollaborateur = demandeFormation.Ep.IdCollaborateur; // devra être utilisé pour notifier le collaborateur demandeFormation.Etat = demandeFormationDTO.EtatDemande; demandeFormation.CommentaireRefus = demandeFormationDTO.CommentaireRefus; demandeFormation.DateDerniereReponse = DateTime.Now; if (demandeFormation.ParticipationFormation != null) epContext.Remove(demandeFormation.ParticipationFormation); await epContext.SaveChangesAsync(); if (demandeFormationDTO.Formation != null && demandeFormationDTO.Formation.Id.HasValue) { int nbParticipations = await epContext.ParticipationFormation.Include(p => p.DemandeFormation).Where(p => p.Formation.IdFormation == demandeFormationDTO.Formation.Id.Value).CountAsync(); demandeFormationDTO.Formation.NbParticipations = nbParticipations; } demandeFormationDTO.EtatDemande = demandeFormation.Etat; demandeFormationDTO.DateDerniereReponse = demandeFormation.DateDerniereReponse; return demandeFormationDTO; } /// /// Vérifier si un objet DemandeFormationDTO est valide pour une mise à jour. /// /// /// Un objet DemandeFormationDTO est valide si l'objet n'est pas null, si le libellé, la descritpion, /// la date de demande de début et la valeur permettant de dire si la demande a été créé par une RH ou non ne sont pas null. /// /// /// /// true si l'objet est valide, false sinon private void IsDemandeFormationValide(DemandeFormationDTO demande) { // Vérifier que la demande de formation n'est pas null if (demande == null) throw new DemandeFormationInvalidException("Aucune évaluation n'a été reçue."); // Vérifier que la demande de formation a bien un libellé if (string.IsNullOrWhiteSpace(demande.Libelle)) throw new DemandeFormationInvalidException("Le libellé de la demande de formation doit contenir au moins 1 caractère."); // Vérifier que la demande de formation a bien une description if (string.IsNullOrWhiteSpace(demande.Description)) throw new DemandeFormationInvalidException("La description de la demande de formation doit contenir au moins 1 caractère."); // Vérifier que la demande de formation a bien une valeur permettant de dire s'il s'agit d'une demande créée par une RH ou non if (!demande.DemandeRH.HasValue) throw new DemandeFormationInvalidException("Impossible de répondre à une demande de formation sans savoir si la demande a été créé par une RH ou non."); // Vérifier que la demande de formation a bien une date de demande if (!demande.DateDemande.HasValue) throw new DemandeFormationInvalidException("Une date de demande de formation est requise."); // Vérifier que la demande de formation a bien un collaborateur if (demande.Collaborateur == null || !demande.Collaborateur.Id.HasValue) throw new DemandeFormationInvalidException("Un collaborateur est requis pour une demande de formation."); // Vérifier que la demande de formation a bien un collaborateur if (demande.Origine == null || !demande.Origine.Id.HasValue) throw new DemandeFormationInvalidException("Une origine de formation est requise pour une demande de formation."); } /// /// Ajouter un ordonnancement croissant ou décroissant sur une colonne. /// /// /// /// /// private IEnumerable OrderByColumn(IEnumerable query, bool? asc, string columnName) { if (!asc.HasValue) asc = defaultAsc; if (string.IsNullOrWhiteSpace(columnName)) return OrderByDefault(query, (bool)asc); if ((bool)asc) return OrderByAscending(query, columnName); else return OrderByDescending(query, columnName); } /// /// Ajouter un ordonnancement croissant sur une colonne. /// /// /// /// private IEnumerable OrderByAscending(IEnumerable query, string columnName) { switch (columnName.ToLower()) { case "businessunit": return query.OrderBy(d => d.Collaborateur.BusinessUnit.Nom); case "collaborateur": return query.OrderBy(d => d.Collaborateur.Nom); case "datedemande": return query.OrderBy(d => d.DateDemande); case "demanderh": return query.OrderBy(d => d.DemandeRH); case "etat": return query.OrderBy(d => d.EtatDemande); case "datereponse": return query.OrderBy(d => d.DateDerniereReponse); default: return query.OrderBy(p => p.Collaborateur.Nom); } } /// /// Ajouter un ordonnancement décroissant sur une colonne. /// /// /// /// private IEnumerable OrderByDescending(IEnumerable query, string columnName) { switch (columnName.ToLower()) { case "businessunit": return query.OrderByDescending(d => d.Collaborateur.BusinessUnit.Nom); case "collaborateur": return query.OrderByDescending(d => d.Collaborateur.Nom); case "datedemande": return query.OrderByDescending(d => d.DateDemande); case "demanderh": return query.OrderByDescending(d => d.DemandeRH); case "etat": return query.OrderByDescending(d => d.EtatDemande); case "datereponse": return query.OrderByDescending(d => d.DateDerniereReponse); default: return query.OrderByDescending(d => d.Collaborateur.Nom); } } /// /// Ajouter un ordonnancement par défaut. /// /// /// /// private IEnumerable OrderByDefault(IEnumerable query, bool asc) { if (asc) return query.OrderBy(p => p.Collaborateur.Nom); else return query.OrderByDescending(p => p.Collaborateur.Nom); } /// /// Ajouter un filtre pour récupérer les demandes de formation en fonction du statut de l'EP. /// /// /// /// private IQueryable StatutEpFilter(IQueryable query) { IEnumerable statutsEp = Enum.GetValues(typeof(StatutEp)).Cast().Where(statut => statut == StatutEp.Cree || EstEpEnCours(statut)); return query.Where(demandeFormation => statutsEp.Contains(demandeFormation.Ep.Statut)); } /// /// Ajouter un filtre pour récupérer les demandes de formation en fonction de plusieurs états de demande. /// /// /// /// private IQueryable EtatsDemandeFilter(IQueryable query, List etatsDemande) { if (etatsDemande != null && etatsDemande.Count > 0) return query.Where(demandeFormation => etatsDemande.Contains(demandeFormation.Etat)); else return query; } /// /// Ajouter un filtre pour récupérer les demandes de formation en fonction de l'id BU des collaborateurs. /// /// /// /// private IQueryable IdBUsFilter(IQueryable query, List idBus) { if (idBus != null && idBus.Count > 0) return query.Where(demandeFormation => idBus.Contains(demandeFormation.Ep.IdBu)); else return query; } /// /// Ajouter un filtre pour récupérer les formations en fonction d'un intervalle de date. /// /// /// /// /// private IQueryable DateFilter(IQueryable query, DateTime? dateDebut, DateTime? dateFin) { if (dateDebut.HasValue && dateFin.HasValue) return query.Where(demandeFormation => demandeFormation.DateDemande >= dateDebut.Value && demandeFormation.DateDemande <= dateFin.Value.AddDays(1)); else if (!dateDebut.HasValue && dateFin.HasValue) return query.Where(demandeFormation => demandeFormation.DateDemande <= dateFin.Value.AddDays(1)); else if (dateDebut.HasValue && !dateFin.HasValue) return query.Where(demandeFormation => demandeFormation.DateDemande >= dateDebut.Value); else return query; } /// /// Ajouter un filtre pour récupérer les demandes de formation en fonction du nom et du prénom du collaborateur. /// /// /// /// private IEnumerable CollaborateurFilter(IEnumerable demandeFormationDTOs, string texte) { if (string.IsNullOrWhiteSpace(texte)) return demandeFormationDTOs; return demandeFormationDTOs.Where(demandeFormation => (demandeFormation.Ep.Collaborateur.Nom + " " + demandeFormation.Ep.Collaborateur.Prenom).ToLower().Contains(texte.ToLower()) || (demandeFormation.Ep.Collaborateur.Prenom + " " + demandeFormation.Ep.Collaborateur.Nom).ToLower().Contains(texte.ToLower())); } /// /// Ajouter une pagination. /// /// /// /// /// private IQueryable SkipAndTake(IQueryable 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); } private bool EstEpEnCours(StatutEp statut) { return statut != StatutEp.Annule && statut != StatutEp.Cree && statut != StatutEp.Rejete && statut != StatutEp.Signe; } #endregion } }