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
{
/// <summary>
/// Service permettant de gérer les notes (ajout, récupération, mise à jour, suppression)
/// </summary>
public class NoteService : INoteService
{
#region Variables
private readonly ICollaborateurApi collaborateurApi ;
/// <summary>
/// Contexte pour interagir avec la base de données MySQL du serveur EP
/// </summary>
private readonly EpContext context ;
/// <summary>
/// Service collaborateur pour récupérer les données collaborateurs au format DTO
/// </summary>
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
/// <summary>
/// Ajouter une nouvelle note dans la base de données de manière async
/// </summary>
/// <param name="nouvelleNote">La nouvelle note a ajouté en base</param>
/// <returns>La nouvelle note ajouté</returns>
public async Task < DetailsNoteDTO > 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 ;
}
/// <summary>
/// Supprimer une note en fonction de son Id de manière async
/// </summary>
/// <param name="idNote">Id de la note à supprimer</param>
public async Task < bool > 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 ;
}
/// <summary>
/// Récupérer une note en fonction de son id de manière async
/// </summary>
/// <param name="idNote">Id de la note à récupérer</param>
/// <returns>L'objet DTO de la note correspondant à l'id passé en paramètre</returns>
public async Task < DetailsNoteDTO > 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 ) ;
}
/// <summary>
/// Récupérer la liste des notes qu'un auteur a écrit sur un collaborateur
/// </summary>
/// <param name="idAuteur">Id de l'auteur des notes à récupérer</param>
/// <param name="asc">Précise si la liste est trié dans l'ordre croissant ou décroissant</param>
/// <param name="numPage">Numéro de la page qui est affiché du côté front</param>
/// <param name="parPage">Nombre de notes à renvoyer</param>
/// <param name="texte">permet de récupérer les notes les informations du collaborateur ou le titre de la note contient le texte</param>
/// <param name="tri">Choisir l'attribut par lequel est trié la liste</param>
/// <returns>Retour la liste des notes à afficher</returns>
public async Task < IEnumerable < AffichageNoteDTO > > 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 < Note > notes = context . Note . Where ( n = > n . IdAuteur = = idAuteur ) ;
var task = notes . Select ( n = > NoteToAffichageDTOAsync ( n ) ) ;
IEnumerable < AffichageNoteDTO > 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 . Skip ( skip ) . Take ( take ) ;
}
/// <summary>
/// Récupérer le nombre de notes qu'un auteur a écrit
/// </summary>
/// <param name="idAuteur">Id de l'auteur des notes à récupérer</param>
/// <param name="texte">permet de récupérer les notes les informations du collaborateur ou le titre de la note contient le texte</param>
/// <returns>Le nombre de notes</returns>
public async Task < int > 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 < Note > notes = context . Note . Where ( n = > n . IdAuteur = = idAuteur ) ;
var task = notes . Select ( n = > NoteToAffichageDTOAsync ( n ) ) ;
IEnumerable < AffichageNoteDTO > 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 ( ) ;
}
/// <summary>
/// Mettre à jour une note
/// </summary>
/// <param name="idNote">Id de la note à modifier</param>
/// <param name="note">Note avec les informations à jour</param>
/// <returns>La note mise à jour</returns>
public async Task < DetailsNoteDTO > 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
/// <summary>
/// Vérfier si la note est valide
/// </summary>
/// <param name="note">La note a vérifié</param>
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" ) ;
}
/// <summary>
/// Vérifier que l'auteur de la note existe et est toujours présent dans l'entreprise
/// </summary>
/// <param name="referent">L'auteur de la note</param>
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" ) ;
}
/// <summary>
/// Vérifier que le collaborateur concerné par la note existe et est toujorus présent dans l'entreprise
/// </summary>
/// <param name="collaborateur">Le collaborateur concerné</param>
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
/// <summary>
/// Transformer un objet note en objet pour afficher un note dans dans un tableau
/// </summary>
/// <param name="note">Note à transformer</param>
/// <param name="collaborateurService">Service collaborateur pour récupérer les informations des collaborateurs</param>
/// <returns>La note transformée pour être affichée</returns>
private async Task < AffichageNoteDTO > 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 ;
}
/// <summary>
/// Transformatino d'une note en DetailsNoteDTO de manière asynchrone
/// </summary>
/// <param name="note">Note à transformer</param>
/// <returns>Note transformer en DetailsNoteDTO</returns>
private async Task < DetailsNoteDTO > 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
/// <summary>
/// Transformer l'objet DTO d'une note en note
/// </summary>
/// <remarks>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à</remarks>
/// <param name="detailsNoteDTO">Objet DTO à transformer en note</param>
/// <returns>L'objet DTO transformé en note</returns>
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
}
}