using EPAServeur.Context; using EPAServeur.Exceptions; using EPAServeur.IServices; using EPAServeur.Models.Notes; using IO.Swagger.ApiCollaborateur; using IO.Swagger.DTO; using IO.Swagger.ModelCollaborateur; using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; namespace EPAServeur.Services { /// /// Service permettant de gérer les notes (ajout, récupération, mise à jour, suppression) /// public class NoteService : INoteService { #region Variables private readonly ICollaborateurApi collaborateurApi; /// /// Contexte pour interagir avec la base de données MySQL du serveur EP /// private readonly EpContext context; /// /// Service collaborateur pour récupérer les données collaborateurs au format DTO /// private readonly ICollaborateurService collaborateurService; #endregion #region Constructeurs public NoteService(ICollaborateurApi _collaborateurApi, ICollaborateurService _collaborateurService, EpContext _context) { collaborateurService = _collaborateurService; collaborateurApi = _collaborateurApi; context = _context; } #endregion #region Services Async /// /// Ajouter une nouvelle note dans la base de données de manière async /// /// La nouvelle note a ajouté en base /// La nouvelle note ajouté public async Task AjouterNoteAsync(DetailsNoteDTO nouvelleNote) { //vérifier qu'il n'y a aucune valeur null CheckNoteValide(nouvelleNote); //vérifier que le référent existe Collaborateur auteur = await collaborateurApi.ChercherCollabIdAsync((Guid?)nouvelleNote.IdAuteur); CheckReferent(auteur); //vérifier que le collaborateur existe Collaborateur collaborateur = await collaborateurApi.ChercherCollabIdAsync(nouvelleNote.Collaborateur.Id); CheckCollaborateur(collaborateur); //transformer la note DTO en Note Note note = DetailsNoteDTOToNouvelleNote(nouvelleNote); //ajouter la note et sauvegarder await context.Note.AddAsync(note); await context.SaveChangesAsync(); nouvelleNote.Id = note.IdNote; return nouvelleNote; } /// /// Supprimer une note en fonction de son Id de manière async /// /// Id de la note à supprimer public async Task SupprimerNoteAsync(long? idNote) { Note note = await context.Note.FindAsync(idNote); if (note == null) { throw new NoteNotFoundException("Impossible de supprimer la note car elle n'a pas été trouvée"); } context.Remove(note); await context.SaveChangesAsync(); return true; } /// /// Récupérer une note en fonction de son id de manière async /// /// Id de la note à récupérer /// L'objet DTO de la note correspondant à l'id passé en paramètre public async Task GetNoteByIdAsync(long? idNote) { Note note = await context.Note.FindAsync(idNote); //vérifier l'existance de la note if (note == null) throw new NoteNotFoundException("La note cherchée n'a pas été trouvée"); //vérifier l'existence de l'auteur Collaborateur auteur = await collaborateurApi.ChercherCollabIdAsync(note.IdAuteur); if (auteur == null) throw new ReferentNotFoundException("L'auteur de la note n'existe pas"); return await NoteToDetailSDTOAsync(note); } /// /// Récupérer la liste des notes qu'un auteur a écrit sur un collaborateur /// /// Id de l'auteur des notes à récupérer /// Précise si la liste est trié dans l'ordre croissant ou décroissant /// Numéro de la page qui est affiché du côté front /// Nombre de notes à renvoyer /// permet de récupérer les notes les informations du collaborateur ou le titre de la note contient le texte /// Choisir l'attribut par lequel est trié la liste /// Retour la liste des notes à afficher public async Task> GetNotesByAuteurAsync(Guid? idAuteur, bool? asc, int? numPage, int? parPage, string texte, string tri) { Collaborateur auteur = await collaborateurApi.ChercherCollabIdAsync(idAuteur); if (auteur == null) throw new ReferentNotFoundException("L'auteur de la note n'existe pas"); int skip = (numPage.Value - 1) * parPage.Value; int take = parPage.Value; IEnumerable notes = context.Note.Where(n => n.IdAuteur == idAuteur); var task = notes.Select(n => NoteToAffichageDTOAsync(n)); IEnumerable AffichageNoteDTO = await Task.WhenAll(task); if (texte != null) { texte = texte.ToLower(); AffichageNoteDTO = (from a in AffichageNoteDTO where a.Collaborateur.ToLower().Contains(texte) || a.Titre.ToLower().Contains(texte) select a); } AffichageNoteDTO = Tri(AffichageNoteDTO, tri); if( asc.HasValue && !asc.Value) { AffichageNoteDTO = AffichageNoteDTO.Reverse(); } return AffichageNoteDTO.Skip(skip).Take(take); } /// /// Récupérer le nombre de notes qu'un auteur a écrit /// /// Id de l'auteur des notes à récupérer /// permet de récupérer les notes les informations du collaborateur ou le titre de la note contient le texte /// Le nombre de notes public async Task GetNotesByAuteurCountAsync(Guid? idAuteur, string texte) { Collaborateur auteur = await collaborateurApi.ChercherCollabIdAsync(idAuteur); if (auteur == null) throw new ReferentNotFoundException("L'auteur de la note n'existe pas"); IEnumerable notes = context.Note.Where(n => n.IdAuteur == idAuteur); var task = notes.Select(n => NoteToAffichageDTOAsync(n)); IEnumerable AffichageNoteDTO = await Task.WhenAll(task); if (texte != null) { texte = texte.ToLower(); AffichageNoteDTO = (from a in AffichageNoteDTO where a.Collaborateur.ToLower().Contains(texte) || a.Titre.ToLower().Contains(texte) select a); } return AffichageNoteDTO.Count(); } /// /// Mettre à jour une note /// /// Id de la note à modifier /// Note avec les informations à jour /// La note mise à jour public async Task UpdateNoteAsync(long? idNote, DetailsNoteDTO note) { if (idNote != note.Id) throw new NoteIdImcompatibleException("L'id de la note a mettre à jour et la note a mettre à jour sont incompatble"); CheckNoteValide(note); Note noteToUpdate = await context.Note.FindAsync(idNote); if (!noteToUpdate.DateCreation.Equals(note.DateCreation) || note.Collaborateur.Id != noteToUpdate.IdCollaborateur || note.IdAuteur != noteToUpdate.IdAuteur) throw new NoteIdImcompatibleException("La note a mettre à jour et la note en base de données ne correspondent pas"); noteToUpdate.Titre = note.Titre; noteToUpdate.Texte = note.Texte; noteToUpdate.DateMiseAJour = DateTime.Now; note.DateMiseAjour = DateTime.Now; await context.SaveChangesAsync(); return await NoteToDetailSDTOAsync(noteToUpdate); } #endregion #region fonctions privees /// /// Vérfier si la note est valide /// /// La note a vérifié private void CheckNoteValide(DetailsNoteDTO note) { //vérifier que la note n'est pas null if (note == null) throw new NoteInvalideException("Aucune note n'a été reçue"); //vérfier que la note a bien un auteur if (note.IdAuteur == null || !note.IdAuteur.HasValue) throw new NoteInvalideException("Il impossible d'enregistrer sans donnée sur la personne qui l'a écrite"); //vérifier que la note est bien lié à un collaboarteur identifiable sur le serveur distant (avec une id) if (note.Collaborateur == null || note.Collaborateur.Id == null || !note.Collaborateur.Id.HasValue) throw new NoteInvalideException("Il est impossible d'enregistrer une note qui n'est pas lié à un collaborateur"); //vérifier que le titre de la note est valide if (note.Titre == null || note.Titre == "" || note.Titre.Length < 3) throw new NoteInvalideException("Vous devez saisir un titre d'au moins 3 caractères"); //vérifier que le texte de la note est valide if(note.Texte == null || note.Texte == "" || note.Texte.Length < 3) throw new NoteInvalideException("Vous devez saisir une note d'au moins 3 caractères"); } /// /// Vérifier que l'auteur de la note existe et est toujours présent dans l'entreprise /// /// L'auteur de la note private void CheckReferent(Collaborateur auteur) { if (auteur == null) throw new ReferentNotFoundException("Les informations de l'auteur de la note n'ont pas été trouvé"); if (auteur.DateDepart.HasValue) throw new CollaborateurPartiException("Vous ne pouvez pas créer ou modifier de note si vous avez quitté l'entreprise"); } private IEnumerable Tri(IEnumerable affichageNoteDTOs, string tri) { return tri switch { "collaborateur" => affichageNoteDTOs.OrderBy(n => n.Collaborateur), "datemiseajour" => affichageNoteDTOs.OrderBy(n => n.DateMiseAJour), "titre" => affichageNoteDTOs.OrderBy(n => n.Titre), _ => affichageNoteDTOs, }; } /// /// Vérifier que le collaborateur concerné par la note existe et est toujorus présent dans l'entreprise /// /// Le collaborateur concerné private void CheckCollaborateur(Collaborateur collaborateur) { if (collaborateur == null) throw new CollaborateurNotFoundException("Le collaborateur pour qui la note est écrite n'a pas été trouvé"); if (collaborateur.DateDepart.HasValue) throw new CollaborateurPartiException("Vous ne pouvez pas créer ou modifier de notes pour un collaborateur qui a quitté l'entreprise"); } #endregion #region ObjectToDTO /// /// Transformer un objet note en objet pour afficher un note dans dans un tableau /// /// Note à transformer /// Service collaborateur pour récupérer les informations des collaborateurs /// La note transformée pour être affichée private async Task NoteToAffichageDTOAsync(Note note) { string infoCollab = "Aucun collaborateur lié"; Collaborateur collaborateur = await collaborateurApi.ChercherCollabIdAsync((Guid?)note.IdCollaborateur); if (collaborateur != null) infoCollab = collaborateur.Prenom + " " + collaborateur.Nom; AffichageNoteDTO affichage = new AffichageNoteDTO() { Id = note.IdNote, IdCollaborateur = note.IdCollaborateur, Collaborateur = infoCollab, Titre = note.Titre, DateMiseAJour = note.DateMiseAJour }; return affichage; } /// /// Transformatino d'une note en DetailsNoteDTO de manière asynchrone /// /// Note à transformer /// Note transformer en DetailsNoteDTO private async Task NoteToDetailSDTOAsync(Note note) { CollaborateurDTO collaborateur = await collaborateurService.GetCollaborateurByIdAsync(note.IdCollaborateur); if (collaborateur == null) throw new CollaborateurNotFoundException("Il est impossible de récupérer une note donc le collaborateur n'existe plus"); DetailsNoteDTO details = new DetailsNoteDTO() { Id = note.IdNote, DateCreation = note.DateCreation, DateMiseAjour = note.DateMiseAJour, Titre = note.Titre, Texte = note.Texte, IdAuteur = note.IdAuteur, Collaborateur = collaborateur, }; return details; } #endregion #region DTOToObject /// /// Transformer l'objet DTO d'une note en note /// /// En général, de base, cette méthode est prévue pour être utilisée qu'à la création d'une nouvelle note, dateCreation et dateUpdate sont donc initialisée à ce moment là /// Objet DTO à transformer en note /// L'objet DTO transformé en note private Note DetailsNoteDTOToNouvelleNote(DetailsNoteDTO detailsNoteDTO) { Note note = new Note() { IdAuteur = detailsNoteDTO.IdAuteur.Value, IdCollaborateur = detailsNoteDTO.Collaborateur.Id.Value, Texte = detailsNoteDTO.Texte, Titre = detailsNoteDTO.Titre, DateCreation = detailsNoteDTO.DateCreation.Value, DateMiseAJour = detailsNoteDTO.DateMiseAjour.Value }; return note; } #endregion } }