diff --git a/EPAServeur.Tests/Controllers/EngagementsApiTests.cs b/EPAServeur.Tests/Controllers/EngagementsApiTests.cs new file mode 100644 index 0000000..c2de69f --- /dev/null +++ b/EPAServeur.Tests/Controllers/EngagementsApiTests.cs @@ -0,0 +1,340 @@ +using EPAServeur.Context; +using EPAServeur.Exceptions; +using EPAServeur.Models.Formation; +using EPAServeur.Services; +using IO.Swagger.Controllers; +using IO.Swagger.DTO; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.DependencyInjection; +using EPAServeur.IServices; +using Moq; +using IO.Swagger.ApiCollaborateur; +using IO.Swagger.Enum; + +namespace EPAServeur.Tests.Controllers +{ + [TestFixture] + public class EngagementsApiTests + { + #region Variables + + private IEngagementService engagementService; + private Mock mockEnvironment; + private EpContext epContext; + #endregion + + #region Setup + + [SetUp] + public void Setup() + { + // Création d'une collection de services pour l'injection de dépendance + var services = new ServiceCollection(); + + // Utilisation d'une base de données en mémoire + var optionBuider = new DbContextOptionsBuilder() + .UseInMemoryDatabase("server_ep_test") + .Options; + + services.AddDbContext(b => b.UseInMemoryDatabase("server_ep_test")); + + epContext = new EpContext(optionBuider); + + epContext.Database.EnsureDeleted(); + epContext.Database.EnsureCreated(); + epContext.SaveChanges(); + + // Ajout du jeu de données pour les tests + DataSeeder.AddEngagements(epContext); + + // Détache les entités du context car la base de données InMemory créé des conflits + // entre les clés primaires lors d'un Update ou d'un Insert + foreach (var entity in epContext.ChangeTracker.Entries()) + { + entity.State = EntityState.Detached; + } + + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + + // Récupčre le service qui sera utilsé pour tester le contrôleur + var serviceProvider = services.BuildServiceProvider(); + engagementService = serviceProvider.GetService(); + + // Simule l'interface IWebHostEnvironment avec Moq + mockEnvironment = new Mock(); + + mockEnvironment + .Setup(m => m.EnvironmentName) + .Returns("Development"); + + } + + #endregion + + + #region Tests GetEngagements + + [Test] + public void GetEngagements_PasseDesParamsPresentsDansLaBDD_RetourneUnObjetOkResult() + { + // Arrange + EngagementsApiController engagementsApiController = new EngagementsApiController(engagementService, new NullLogger(), mockEnvironment.Object); + List idBUs = new List { 1, 2 }; + + // Act + var okResult = engagementsApiController.GetEngagements(idBUs, null, true, 1, 5, null, null); + + // Assert + Assert.IsInstanceOf(okResult.Result); + } + + [Test] + public void GetEngagements_PasseDesParamsPresentsDansLaBDD_RetourneLesCinqPremiersEngagements() + { + // Arrange + EngagementsApiController engagementsApiController = new EngagementsApiController(engagementService, new NullLogger(), mockEnvironment.Object); + List idBUs = new List { 1, 2 }; + int nbEngagement = 5; + int idFirstEngagement = 2; + int idLastEngagement = 10; + + // Act + var okResult = engagementsApiController.GetEngagements(idBUs, null, true, 1, 5, null, null).Result as OkObjectResult; + + // Assert + Assert.IsInstanceOf>(okResult.Value); + Assert.AreEqual(nbEngagement, (okResult.Value as IEnumerable).Count()); + Assert.AreEqual(idFirstEngagement, (okResult.Value as IEnumerable).First().Id); + Assert.AreEqual(idLastEngagement, (okResult.Value as IEnumerable).Last().Id); + } + + #endregion + + #region Tests GetEngagementsCount + + [Test] + public void GetEngagementsCount_PasseDesParamsPresentsDansLaBDD_RetourneUnObjetOkResult() + { + // Arrange + EngagementsApiController engagementsApiController = new EngagementsApiController(engagementService, new NullLogger(), mockEnvironment.Object); + List idBUs = new List { 1, 2 }; + + // Act + var okResult = engagementsApiController.GetEngagementsCount(idBUs, null, true, 1, 5, null, null); + + // Assert + Assert.IsInstanceOf(okResult.Result); + } + + [Test] + public void GetEngagementsCount_PasseDesParamsPresentsDansLaBDD_RetourneLeBonNombreDEngagement() + { + // Arrange + EngagementsApiController engagementsApiController = new EngagementsApiController(engagementService, new NullLogger(), mockEnvironment.Object); + List idBUs = new List { 1, 2 }; + int nbEngagement = 5; + + // Act + var okResult = engagementsApiController.GetEngagementsCount(idBUs, null, true, 1, 5, null, null).Result as OkObjectResult; + + // Assert + Assert.IsInstanceOf(okResult.Value); + Assert.AreEqual(nbEngagement, (long)okResult.Value); + } + + #endregion + + #region Tests UpdateEngagement + + [Test] + public void UpdateEngagement_ModifieUnEngagementAvecUnEPInvalide_RetourneUnObjetObjectResultDansCatchEngagementInvalidException() + { + // Arrange + long idEngagement = 1; + EtatEngagement reponse = EtatEngagement.Respecte; + EngagementsApiController engagementsApiController = new EngagementsApiController(engagementService, new NullLogger(), mockEnvironment.Object); + EpInformationDTO epInformationDTO = null; + + EngagementDTO engagementDTO = new EngagementDTO + { + Id = idEngagement, + Action = "Je m'engage ŕ trouver une formation sur l'Asp.Net Core.", + Dispositif = "Demande de formation RH.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2020, 9, 1), + EtatEngagement = reponse, + Ep = epInformationDTO + }; + + // Act + var objectResult = engagementsApiController.UpdateEngagement(engagementDTO, idEngagement); + + // Assert + Assert.IsInstanceOf(objectResult.Result); + } + + [Test] + public void UpdateEngagement_ModifieUnEngagementAvecUnIdEngagementInvalide_RetourneUnObjetObjectResultDansCatchEngagementIncompatibleIdException() + { + // Arrange + long idEngagement = 1; + long idEngagementIncorrecte = 2; + long idEp = 9; + EtatEngagement reponse = EtatEngagement.Respecte; + EngagementsApiController engagementsApiController = new EngagementsApiController(engagementService, new NullLogger(), mockEnvironment.Object); + EpInformationDTO epInformationDTO = epContext.Ep.Where(ep => ep.IdEP == idEp) + .Select(ep => new EpInformationDTO + { + Id = ep.IdEP, + Type = ep.TypeEP, + Statut = ep.Statut, + DateDisponibilite = ep.DateDisponibilite, + DatePrevisionnelle = ep.DatePrevisionnelle, + Obligatoire = ep.Obligatoire + }).FirstOrDefault(); + + EngagementDTO engagementDTO = new EngagementDTO + { + Id = idEngagementIncorrecte, + Action = "Je m'engage ŕ trouver une formation sur l'Asp.Net Core.", + Dispositif = "Demande de formation RH.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2020, 9, 1), + EtatEngagement = reponse, + Ep = epInformationDTO + }; + + // Act + var objectResult = engagementsApiController.UpdateEngagement(engagementDTO, idEngagement); + + // Assert + Assert.IsInstanceOf(objectResult.Result); + } + + [Test] + public void UpdateEngagement_ModifieUnEngagementInexistant_RetourneUnObjetObjectResultDansCatchEngagementNotFoundExceptionn() + { + // Arrange + long idEngagementInexistant = 999; + long idEp = 9; + EtatEngagement reponse = EtatEngagement.Respecte; + EngagementsApiController engagementsApiController = new EngagementsApiController(engagementService, new NullLogger(), mockEnvironment.Object); + EpInformationDTO epInformationDTO = epContext.Ep.Where(ep => ep.IdEP == idEp) + .Select(ep => new EpInformationDTO + { + Id = ep.IdEP, + Type = ep.TypeEP, + Statut = ep.Statut, + DateDisponibilite = ep.DateDisponibilite, + DatePrevisionnelle = ep.DatePrevisionnelle, + Obligatoire = ep.Obligatoire + }).FirstOrDefault(); + EngagementDTO engagementDTO = new EngagementDTO + { + Id = idEngagementInexistant, + Action = "Toto.", + Dispositif = "Tata.", + Modalite = "Titi", + DateLimite = new DateTime(2020, 9, 1), + EtatEngagement = reponse, + Ep = epInformationDTO + }; + + // Act + var objectResult = engagementsApiController.UpdateEngagement(engagementDTO, idEngagementInexistant); + + // Assert + Assert.IsInstanceOf(objectResult.Result); + } + + [Test] + public void UpdateEngagement_ModifieUnEngagementValide_RetourneUnObjetOkObjectResult() + { + // Arrange + long idEngagement = 1; + long idEp = 9; + EtatEngagement reponse = EtatEngagement.Respecte; + EngagementsApiController engagementsApiController = new EngagementsApiController(engagementService, new NullLogger(), mockEnvironment.Object); + EpInformationDTO epInformationDTO = epContext.Ep.Where(ep => ep.IdEP == idEp) + .Select(ep => new EpInformationDTO + { + Id = ep.IdEP, + Type = ep.TypeEP, + Statut = ep.Statut, + DateDisponibilite = ep.DateDisponibilite, + DatePrevisionnelle = ep.DatePrevisionnelle, + Obligatoire = ep.Obligatoire + }).FirstOrDefault(); + + EngagementDTO engagementDTO = new EngagementDTO + { + Id = idEngagement, + Action = "Je m'engage ŕ trouver une formation sur l'Asp.Net Core.", + Dispositif = "Demande de formation RH.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2020, 9, 1), + EtatEngagement = reponse, + Ep = epInformationDTO + }; + + // Act + var okObjectResult = engagementsApiController.UpdateEngagement(engagementDTO, idEngagement); + + // Assert + Assert.IsInstanceOf(okObjectResult.Result); + } + + [Test] + public void UpdateEngagement_ModifieUnEngagementValide_RetourneLEngagementModifie() + { + // Arrange + long idEngagement = 1; + long idEp = 9; + EtatEngagement reponse = EtatEngagement.Respecte; + EngagementsApiController engagementsApiController = new EngagementsApiController(engagementService, new NullLogger(), mockEnvironment.Object); + EpInformationDTO epInformationDTO = epContext.Ep.Where(ep => ep.IdEP == idEp) + .Select(ep => new EpInformationDTO + { + Id = ep.IdEP, + Type = ep.TypeEP, + Statut = ep.Statut, + DateDisponibilite = ep.DateDisponibilite, + DatePrevisionnelle = ep.DatePrevisionnelle, + Obligatoire = ep.Obligatoire + }).FirstOrDefault(); + + EngagementDTO engagementDTO = new EngagementDTO + { + Id = idEngagement, + Action = "Je m'engage ŕ trouver une formation sur l'Asp.Net Core.", + Dispositif = "Demande de formation RH.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2020, 9, 1), + EtatEngagement = reponse, + Ep = epInformationDTO + }; + + // Act + var okObjectResult = engagementsApiController.UpdateEngagement(engagementDTO, idEngagement).Result as OkObjectResult; + + // Assert + Assert.IsInstanceOf(okObjectResult.Value); + Assert.AreEqual(reponse, (okObjectResult.Value as EngagementDTO).EtatEngagement); + } + + #endregion + + } +} \ No newline at end of file diff --git a/EPAServeur.Tests/Services/EngagementServiceTests.cs b/EPAServeur.Tests/Services/EngagementServiceTests.cs new file mode 100644 index 0000000..8c25bc7 --- /dev/null +++ b/EPAServeur.Tests/Services/EngagementServiceTests.cs @@ -0,0 +1,637 @@ +using EPAServeur.Context; +using EPAServeur.Exceptions; +using EPAServeur.IServices; +using EPAServeur.Models.Formation; +using EPAServeur.Services; +using IO.Swagger.ApiCollaborateur; +using IO.Swagger.DTO; +using IO.Swagger.Enum; +using Microsoft.EntityFrameworkCore; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace EPAServeur.Tests.Services +{ + [TestFixture] + public class EngagementServiceTests + { + #region Variables + + private EpContext epContext; + private ICollaborateurApi collaborateurApi; + private ICollaborateurService collaborateurService; + #endregion + + #region Setup + + [SetUp] + public void Setup() + { + // Utilisation d'une base de données en mémoire + var optionBuider = new DbContextOptionsBuilder() + .UseInMemoryDatabase("server_ep_test") + .Options; + + epContext = new EpContext(optionBuider); + collaborateurApi = new CollaborateurApi(); + collaborateurService = new CollaborateurService(collaborateurApi, epContext); + epContext.Database.EnsureDeleted(); + epContext.Database.EnsureCreated(); + epContext.SaveChanges(); + + // Ajout du jeu de données pour les tests + DataSeeder.AddEngagements(epContext); + + // Détache les entités du context car la base de données InMemory créé des conflits + // entre les clés primaires lors d'un Update ou d'un Insert + foreach (var entity in epContext.ChangeTracker.Entries()) + { + entity.State = EntityState.Detached; + } + } + + #endregion + + #region Tests GetEngagementsAsync + + [TestCase(new long[] { 1, 2 })] + [TestCase(new long[] { 3 })] + public async Task GetEngagementsAsync_PasseDesParamsDesIdBUValides_RetourneDesEngagements(long[] arrIdBUs) + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs = arrIdBUs.Select(x => x).ToList(); + + // Act + IEnumerable engagementDTOs = await engagementService.GetEngagementsAsync(idBUs, null, null, null, null, null, null); + + // Assert + Assert.Less(0, engagementDTOs.Count()); + } + + [TestCase(new EtatEngagement[] { EtatEngagement.EnAttente, EtatEngagement.Respecte })] + [TestCase(new EtatEngagement[] { EtatEngagement.DateLimitePassee })] + public async Task GetEngagementsAsync_PasseDesParamsDesEtatsDEngagementsValides_RetourneDesEngagements(EtatEngagement[] arrEtatsEngagement) + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs = new List() { 1, 2, 3 }; + List etatEngagements = arrEtatsEngagement.Select(x => x).ToList(); + + // Act + IEnumerable engagementDTOs = await engagementService.GetEngagementsAsync(idBUs, etatEngagements, null, null, null, null, null); + + // Assert + Assert.Less(0, engagementDTOs.Count()); + } + + [TestCase(1, 5)] + [TestCase(1, 10)] + public async Task GetEngagementsAsync_PasseEnParamNumPageEtParPage_RetourneLaPremierePageDesEngagements(int? numPage, int? parPage) + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs = new List() { 1, 2, 3 }; + + // Act + IEnumerable engagementDTOs = await engagementService.GetEngagementsAsync(idBUs, null, null, numPage, parPage, null, null); + + // Assert + Assert.AreEqual(parPage, engagementDTOs.Count()); + } + + [TestCase(2, 5)] + [TestCase(2, 6)] + [TestCase(2, 10)] + [TestCase(2, 15)] + public async Task GetEngagementsAsync_PasseEnParamNumPageEtParPage_RetourneLaDeuxiemePageDesFormations(int? numPage, int? parPage) + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs = new List() { 1, 2, 3 }; + int? nbEngagementDeuxiemePage; + + switch (parPage) + { + case 5: + nbEngagementDeuxiemePage = 5; + break; + case 6: + nbEngagementDeuxiemePage = 6; + break; + case 10: + nbEngagementDeuxiemePage = 2; + break; + default: + nbEngagementDeuxiemePage = 0; + break; + } + + // Act + IEnumerable engagementDTOs = await engagementService.GetEngagementsAsync(idBUs, null, null, numPage, parPage, null, null); + + // Assert + Assert.AreEqual(nbEngagementDeuxiemePage, engagementDTOs.Count()); + } + + [TestCase(true, "action")] + [TestCase(true, null)] + [TestCase(true, "toto")] + public async Task GetEngagementsAsync_PasseEnParamAscEtTri_RetourneDesEngagementsOrdonnancesParActionCroissant(bool? asc, string tri) + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs = new List() { 1, 2, 3 }; + + // Act + IEnumerable engagementDTOs = await engagementService.GetEngagementsAsync(idBUs, null, asc, null, null, null, tri); + + // Assert + Assert.AreEqual("Je m'engage ŕ attribuer 5 jours de congés supplémentaire.", engagementDTOs.First().Action); + Assert.AreEqual("Je m'engage ŕ trouver une formation sur le Cobol.", engagementDTOs.Last().Action); + } + + [TestCase(false, "action")] + [TestCase(false, null)] + [TestCase(false, "toto")] + public async Task GetEngagementsAsync_PasseEnParamAscEtTri_RetourneDesEngagementsOrdonnancesParActionDecroissant(bool? asc, string tri) + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs = new List() { 1, 2, 3 }; + + // Act + IEnumerable engagementDTOs = await engagementService.GetEngagementsAsync(idBUs, null, asc, null, null, null, tri); + + // Assert + Assert.AreEqual("Je m'engage ŕ trouver une formation sur le Cobol.", engagementDTOs.First().Action); + Assert.AreEqual("Je m'engage ŕ attribuer 5 jours de congés supplémentaire.", engagementDTOs.Last().Action); + } + + [Test] + public async Task GetEngagementsAsync_PasseEnParamAscEtTri_RetourneDesEngagementsOrdonnancesParDispositifCroissant() + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs = new List() { 1, 2, 3 }; + bool? asc = true; + string tri = "dispositif"; + + // Act + IEnumerable engagementDTOs = await engagementService.GetEngagementsAsync(idBUs, null, asc, null, null, null, tri); + + // Assert + Assert.AreEqual("Contacter le client pour planifier un rendez-vous.", engagementDTOs.First().Dispositif); + Assert.AreEqual("Planifier un point hebdomadaire sur Teams.", engagementDTOs.Last().Dispositif); + } + + [Test] + public async Task GetEngagementsAsync_PasseEnParamAscEtTri_RetourneDesEngagementsOrdonnancesParDispositifDecroissant() + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs = new List() { 1, 2, 3 }; + bool? asc = false; + string tri = "dispositif"; + + // Act + IEnumerable engagementDTOs = await engagementService.GetEngagementsAsync(idBUs, null, asc, null, null, null, tri); + + // Assert + Assert.AreEqual("Planifier un point hebdomadaire sur Teams.", engagementDTOs.First().Dispositif); + Assert.AreEqual("Contacter le client pour planifier un rendez-vous.", engagementDTOs.Last().Dispositif); + } + + [Test] + public async Task GetEngagementsAsync_PasseEnParamAscEtTri_RetourneDesEngagementsOrdonnancesParModaliteCroissante() + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs = new List() { 1, 2, 3 }; + bool? asc = true; + string tri = "modalite"; + + // Act + IEnumerable engagementDTOs = await engagementService.GetEngagementsAsync(idBUs, null, asc, null, null, null, tri); + + // Assert + Assert.AreEqual("Hors temps", engagementDTOs.First().Modalite); + Assert.AreEqual("Sur temps de travail", engagementDTOs.Last().Modalite); + } + + [Test] + public async Task GetEngagementsAsync_PasseEnParamAscEtTri_RetourneDesEngagementsOrdonnancesParModaliteDecroissante() + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs = new List() { 1, 2, 3 }; + bool? asc = false; + string tri = "modalite"; + + // Act + IEnumerable engagementDTOs = await engagementService.GetEngagementsAsync(idBUs, null, asc, null, null, null, tri); + + // Assert + Assert.AreEqual("Sur temps de travail", engagementDTOs.First().Modalite); + Assert.AreEqual("Hors temps", engagementDTOs.Last().Modalite); + } + + [Test] + public async Task GetEngagementsAsync_PasseEnParamAscEtTri_RetourneDesEngagementsOrdonnancesParDateCroissante() + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs = new List() { 1, 2, 3 }; + bool? asc = true; + string tri = "date"; + + // Act + IEnumerable engagementDTOs = await engagementService.GetEngagementsAsync(idBUs, null, asc, null, null, null, tri); + + // Assert + Assert.AreEqual(new DateTime(2020, 9, 1), engagementDTOs.First().DateLimite); + Assert.AreEqual(new DateTime(2021, 1, 31), engagementDTOs.Last().DateLimite); + } + + [Test] + public async Task GetEngagementsAsync_PasseEnParamAscEtTri_RetourneDesEngagementsOrdonnancesParDateDecroissante() + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs = new List() { 1, 2, 3 }; + bool? asc = false; + string tri = "date"; + + // Act + IEnumerable engagementDTOs = await engagementService.GetEngagementsAsync(idBUs, null, asc, null, null, null, tri); + + // Assert + Assert.AreEqual(new DateTime(2021, 1, 31), engagementDTOs.First().DateLimite); + Assert.AreEqual(new DateTime(2020, 9, 1), engagementDTOs.Last().DateLimite); + } + + [TestCase(new long[] { 0 }, null )] + [TestCase(new long[] { 4 }, null)] + [TestCase(new long[] { 1, 2 }, "azerty")] + + public async Task GetEngagementsAsync_PasseDesParamsInvalides_RetourneZeroEngagement(long[] arrIdBUs, string texte) + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs; + + if (arrIdBUs != null) + idBUs = arrIdBUs.Select(x => x).ToList(); + else + idBUs = new List(); + + // Act + IEnumerable engagementDTOs = await engagementService.GetEngagementsAsync(idBUs, null, null, null, null, texte, null); + + // Assert + Assert.AreEqual(0, engagementDTOs.Count()); + } + + [Test] + public void GetEngagementsAsync_PasseDesParamsUneListeDIdsBUVide_LeveUneEngagementInvalidException() + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs = new List(); + + // Act + AsyncTestDelegate throwException = () => engagementService.GetEngagementsAsync(idBUs, null, null, null, null, null, null); + + // Assert + Assert.ThrowsAsync(typeof(EngagementInvalidException), throwException); + } + + [Test] + public void GetEngagementsAsync_PasseDesParamsUneListeDIdsBUNull_LeveUneEngagementInvalidException() + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs = null; + + // Act + AsyncTestDelegate throwException = () => engagementService.GetEngagementsAsync(idBUs, null, null, null, null, null, null); + + // Assert + Assert.ThrowsAsync(typeof(EngagementInvalidException), throwException); + } + + + #endregion + + #region Tests GetEngagementsCountAsync + + [TestCase(new long[] { 1, 2, 3 }, "formation")] + [TestCase(new long[] { 1 }, null)] + public async Task GetEngagementsCountAsync_PasseDesParamsValides_RetourneLeNombreTotalDEngagements(long[] arrIdBUs, string texte) + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs; + + if (arrIdBUs != null) + idBUs = arrIdBUs.Select(x => x).ToList(); + else + idBUs = new List(); + + // Act + long count = await engagementService.GetEngagementsCountAsync(idBUs, null, null, null, null, texte, null); + + // Assert + Assert.Less(0, count); + } + + [TestCase(new long[] { 0 }, null)] + [TestCase(new long[] { 4 }, null)] + [TestCase(new long[] { 1, 2 }, "azerty")] + public async Task GetEngagementsCountAsync_PasseDesParamsInvalides_RetourneZero(long[] arrIdBUs, string texte) + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + List idBUs; + + if (arrIdBUs != null) + idBUs = arrIdBUs.Select(x => x).ToList(); + else + idBUs = new List(); + + // Act + long count = await engagementService.GetEngagementsCountAsync(idBUs, null, null, null, null, texte, null); + + // Assert + Assert.AreEqual(0, count); + } + + #endregion + + #region Tests RepondreEngagementAsync + + [TestCase(1, 9, EtatEngagement.Respecte, null)] + [TestCase(1, 9, EtatEngagement.EnAttente, null)] + [TestCase(2, 9, EtatEngagement.NonRealisable, "Impossible de respecter cet engagement car hors budget.")] + public async Task RepondreEngagementAsync_ModifieUnEngagementValide_EngagementModifieAvecSucces(long idEngagement, long idEp, EtatEngagement etatEngagement, string raisonNonRealisable) + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + + EpInformationDTO epInformationDTO = epContext.Ep.Where(ep => ep.IdEP == idEp) + .Select(ep => new EpInformationDTO + { + Id = ep.IdEP, + Type = ep.TypeEP, + Statut = ep.Statut, + DateDisponibilite = ep.DateDisponibilite, + DatePrevisionnelle = ep.DatePrevisionnelle, + Obligatoire = ep.Obligatoire + }).FirstOrDefault(); + + EngagementDTO engagementDTO =new EngagementDTO + { + Id = idEngagement, + Action = "Je m'engage ŕ trouver une formation sur l'Asp.Net Core.", + Dispositif = "Demande de formation RH.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2020, 9, 1), + EtatEngagement = etatEngagement, + RaisonNonRealisable = raisonNonRealisable, + Ep = epInformationDTO + }; + + // Act + EngagementDTO engagementModifie = await engagementService.RepondreEngagementAsync(engagementDTO, idEngagement); + + // Assert + Assert.IsNotNull(engagementModifie); + Assert.AreEqual(idEngagement, engagementModifie.Id); + Assert.AreEqual(engagementDTO.Id, engagementModifie.Id); + Assert.AreEqual(engagementDTO.EtatEngagement, engagementModifie.EtatEngagement); + Assert.AreEqual(engagementDTO.RaisonNonRealisable, engagementModifie.RaisonNonRealisable); + } + + [Test] + public async Task RepondreEngagementAsync_ModifieUnEngagementAvecUneDateLimitePasseeValide_EngagementModifieAvecSucces() + { + long idEngagement = 3; + long idEp = 9; + EtatEngagement etatEngagement = EtatEngagement.DateLimitePassee; + string raisonNonRealisableAvantUpdate = null; + string raisonNonRealisableApresUpdate = "La date limite pour respecter l'engagement est passée."; + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + + EpInformationDTO epInformationDTO = epContext.Ep.Where(ep => ep.IdEP == idEp) + .Select(ep => new EpInformationDTO + { + Id = ep.IdEP, + Type = ep.TypeEP, + Statut = ep.Statut, + DateDisponibilite = ep.DateDisponibilite, + DatePrevisionnelle = ep.DatePrevisionnelle, + Obligatoire = ep.Obligatoire + }).FirstOrDefault(); + + EngagementDTO engagementDTO = new EngagementDTO + { + Id = idEngagement, + Action = "Je m'engage ŕ trouver une formation sur l'Asp.Net Core.", + Dispositif = "Demande de formation RH.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2020, 9, 1), + EtatEngagement = etatEngagement, + RaisonNonRealisable = raisonNonRealisableAvantUpdate, + Ep = epInformationDTO + }; + + // Act + EngagementDTO engagementModifie = await engagementService.RepondreEngagementAsync(engagementDTO, idEngagement); + + // Assert + Assert.IsNotNull(engagementModifie); + Assert.AreEqual(idEngagement, engagementModifie.Id); + Assert.AreEqual(engagementDTO.Id, engagementModifie.Id); + Assert.AreEqual(engagementDTO.EtatEngagement, engagementModifie.EtatEngagement); + Assert.AreEqual(raisonNonRealisableApresUpdate, engagementModifie.RaisonNonRealisable); + } + + [TestCase(1, 0, "Je m'engage ŕ trouver une formation sur l'Asp.Net Core.", "Demande de formation RH.", "Sur temps de travail", "2020-9-11", EtatEngagement.Respecte, null)] + [TestCase(1, 11, "Je m'engage ŕ trouver une formation sur l'Asp.Net Core.", "Demande de formation RH.", "Sur temps de travail", "2020-9-11", EtatEngagement.Respecte, null)] + [TestCase(1, 9, "", "Demande de formation RH.", "Sur temps de travail", "2020-9-11", EtatEngagement.Respecte, null)] + [TestCase(1, 9, "Je m'engage ŕ trouver une formation sur l'Asp.Net Core.", "", "Sur temps de travail", "2020-9-11", EtatEngagement.Respecte, null)] + [TestCase(1, 9, "Je m'engage ŕ trouver une formation sur l'Asp.Net Core.", "Demande de formation RH.", "", "2020-9-11", EtatEngagement.Respecte, null)] + [TestCase(1, 9, "Je m'engage ŕ trouver une formation sur l'Asp.Net Core.", "Demande de formation RH.", "Sur temps de travail", null, EtatEngagement.Respecte, null)] + [TestCase(1, 9, "Je m'engage ŕ trouver une formation sur l'Asp.Net Core.", "Demande de formation RH.", "Sur temps de travail", "2020-9-11", EtatEngagement.NonRealisable, null)] + public void RepondreEngagementAsync_ModifieUnEngagementAvecDesProprietesInvalide_LeveUneEngagementInvalidException(long idEngagement, long idEp, string action, string dispositif, string modalite, DateTime? dateLimite, EtatEngagement etatEngagement, string raisonNonRealisable) + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + + EpInformationDTO epInformationDTO = epContext.Ep.Where(ep => ep.IdEP == idEp) + .Select(ep => new EpInformationDTO + { + Id = ep.IdEP, + Type = ep.TypeEP, + Statut = ep.Statut, + DateDisponibilite = ep.DateDisponibilite, + DatePrevisionnelle = ep.DatePrevisionnelle, + Obligatoire = ep.Obligatoire + }).FirstOrDefault(); + + EngagementDTO engagementDTO = new EngagementDTO + { + Id = idEngagement, + Action = action, + Dispositif = dispositif, + Modalite = modalite, + DateLimite = dateLimite, + EtatEngagement = etatEngagement, + RaisonNonRealisable = raisonNonRealisable, + Ep = epInformationDTO + }; + + // Act + AsyncTestDelegate throwException = () => engagementService.RepondreEngagementAsync(engagementDTO, idEngagement); + + // Assert + Assert.ThrowsAsync(typeof(EngagementInvalidException), throwException); + } + + [Test] + public void RepondreEngagementAsync_ModifieUnEngagementNull_LeveUneEngagementInvalidException() + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + EngagementDTO engagementDTO = null; + long idEngagement = 1; + + // Act + AsyncTestDelegate throwException = () => engagementService.RepondreEngagementAsync(engagementDTO, idEngagement); + + // Assert + Assert.ThrowsAsync(typeof(EngagementInvalidException), throwException); + } + + [Test] + public void RepondreEngagementAsync_ModifieUnEngagementAvecUnEPInexistantDansLaBDD_LeveUneEngagementInvalidException() + { + // Arrange + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + long idEngagement = 1; + EpInformationDTO epInformationDTO = new EpInformationDTO + { + Id = 999, + Type = TypeEp.EPA, + Statut = StatutEp.Signe, + DateDisponibilite = DateTime.Now, + DatePrevisionnelle = DateTime.Now, + Obligatoire = false + }; + + EngagementDTO engagementDTO = new EngagementDTO + { + Id = idEngagement, + Action = "Je m'engage ŕ trouver une formation sur l'Asp.Net Core.", + Dispositif = "Demande de formation RH.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2020, 9, 1), + EtatEngagement = EtatEngagement.Respecte, + RaisonNonRealisable = null, + Ep = epInformationDTO + }; + + // Act + AsyncTestDelegate throwException = () => engagementService.RepondreEngagementAsync(engagementDTO, idEngagement); + + // Assert + Assert.ThrowsAsync(typeof(EngagementInvalidException), throwException); + } + + + + [TestCase(1)] + [TestCase(null)] + public void RepondreEngagementAsync_ModifieUnEngagementAvecUnIdIncorrecte_LeveUneEngagementnIncompatibleIdException(long? idEngagement) + { + // Arrange + long idEngagementIncorrecte = 2; + long idEp = 9; + + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + + EpInformationDTO epInformationDTO = epContext.Ep.Where(ep => ep.IdEP == idEp) + .Select(ep => new EpInformationDTO + { + Id = ep.IdEP, + Type = ep.TypeEP, + Statut = ep.Statut, + DateDisponibilite = ep.DateDisponibilite, + DatePrevisionnelle = ep.DatePrevisionnelle, + Obligatoire = ep.Obligatoire + }).FirstOrDefault(); + + EngagementDTO engagementDTO = new EngagementDTO + { + Id = idEngagement, + Action = "Je m'engage ŕ trouver une formation sur l'Asp.Net Core.", + Dispositif = "Demande de formation RH.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2020, 9, 1), + EtatEngagement = EtatEngagement.Respecte, + RaisonNonRealisable = null, + Ep = epInformationDTO + }; + + // Act + AsyncTestDelegate throwException = () => engagementService.RepondreEngagementAsync(engagementDTO, idEngagementIncorrecte); + + // Assert + Assert.ThrowsAsync(typeof(EngagementIncompatibleIdException), throwException); + } + + [Test] + public void RepondreEngagementAsync_ModifieUnEngagementAvecUnIdInexistant_LeveUneEngagementNotFoundException() + { + // Arrange + long idEngagement = 0; + long idEp = 9; + + EngagementService engagementService = new EngagementService(epContext, collaborateurService); + + EpInformationDTO epInformationDTO = epContext.Ep.Where(ep => ep.IdEP == idEp) + .Select(ep => new EpInformationDTO + { + Id = ep.IdEP, + Type = ep.TypeEP, + Statut = ep.Statut, + DateDisponibilite = ep.DateDisponibilite, + DatePrevisionnelle = ep.DatePrevisionnelle, + Obligatoire = ep.Obligatoire + }).FirstOrDefault(); + + EngagementDTO engagementDTO = new EngagementDTO + { + Id = idEngagement, + Action = "Je m'engage ŕ trouver une formation sur l'Asp.Net Core.", + Dispositif = "Demande de formation RH.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2020, 9, 1), + EtatEngagement = EtatEngagement.Respecte, + RaisonNonRealisable = null, + Ep = epInformationDTO + }; + + // Act + AsyncTestDelegate throwException = () => engagementService.RepondreEngagementAsync(engagementDTO, idEngagement); + + // Assert + Assert.ThrowsAsync(typeof(EngagementNotFoundException), throwException); + } + #endregion + } +} \ No newline at end of file diff --git a/EPAServeur/Attributes/CannotBeEmptyAttribute.cs b/EPAServeur/Attributes/CannotBeEmptyAttribute.cs new file mode 100644 index 0000000..b785ba1 --- /dev/null +++ b/EPAServeur/Attributes/CannotBeEmptyAttribute.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections; +using System.ComponentModel.DataAnnotations; + +namespace EPAServeur.Attributes +{ + /// + /// Specifies that a collection of a specified type must have at least one element. + /// + [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] + public sealed class CannotBeEmptyAttribute : RequiredAttribute + { + public override bool IsValid(object value) + { + var list = value as IEnumerable; + return list != null && list.GetEnumerator().MoveNext(); + } + } +} diff --git a/EPAServeur/Context/DataSeeder.cs b/EPAServeur/Context/DataSeeder.cs index a478ee0..92be406 100644 --- a/EPAServeur/Context/DataSeeder.cs +++ b/EPAServeur/Context/DataSeeder.cs @@ -256,63 +256,70 @@ namespace EPAServeur.Context ep9 = new Ep { - IdCollaborateur = Guid.Parse("59a8becb-bc0a-4d3d-adb1-8a8bd13c48c9"), - IdReferent = Guid.Parse("e5d36da4-df16-4d19-8a11-1ba2f6efc80c"), - IdBu = 2, - Fonction = "Dev", + IdEP = 9, + IdCollaborateur = Guid.Parse("842650db-a548-4472-a3af-4c5fff3c1ab8"), + IdReferent = Guid.Parse("aa36f34c-9041-42f5-9db3-6536fe7f1696"), + IdBu = 1, + Fonction = "IngĂ©nieur en Etudes et DĂ©veloppement", TypeEP = TypeEp.EPA, NumeroEp = 1, - DateCreation = new DateTime(2017, 7, 7), - DatePrevisionnelle = new DateTime(2018, 7, 8), + DateCreation = new DateTime(2020, 7, 7), + DatePrevisionnelle = new DateTime(2020, 7, 8), Obligatoire = false, Statut = StatutEp.Signe, CV = "CV.pdf", - DateSaisie = new DateTime(2018, 6, 20) + DateSaisie = new DateTime(2020, 7, 20) }; epContext.Ep.Add(ep9); ep10 = new Ep { - IdCollaborateur = Guid.Parse("a00eb610-d735-4a83-ac5a-7b89cbd4b42d"), - IdReferent = Guid.Parse("d3f69a83-8a29-4971-8d3c-2d0cf320dad2"), - IdBu = 2, - Fonction = "Dev", - TypeEP = TypeEp.EPA, + IdEP = 10, + IdCollaborateur = Guid.Parse("301ba7f3-095e-4912-8998-a7c942dc5f23"), + IdReferent = Guid.Parse("ea027734-ff0f-4308-8879-133a09fb3c46"), + IdBu = 3, + Fonction = "IngĂ©nieur en Etudes et DĂ©veloppement", + TypeEP = TypeEp.EPS, NumeroEp = 1, - DateCreation = new DateTime(2017, 7, 7), - DatePrevisionnelle = new DateTime(2018, 7, 8), + DateCreation = new DateTime(2020, 6, 1), + DatePrevisionnelle = new DateTime(2020, 9, 25), Obligatoire = false, Statut = StatutEp.Signe, CV = "CV.pdf", - DateSaisie = new DateTime(2018, 6, 20) + DateSaisie = new DateTime(2020, 10, 5) }; epContext.Ep.Add(ep10); ep11 = new Ep { - IdCollaborateur = Guid.Parse("a00eb610-d735-4a83-ac5a-7b89cbd4b42d"), - IdReferent = Guid.Parse("d3f69a83-8a29-4971-8d3c-2d0cf320dad2"), + IdEP = 11, + IdCollaborateur = Guid.Parse("a0f40e2a-cc03-4032-a627-5389e1281c64"), + IdReferent = Guid.Parse("c199024f-5960-4c11-8e34-f9947d589284"), IdBu = 2, - Fonction = "Dev", + Fonction = "IngĂ©nieur en Etudes et DĂ©veloppement", TypeEP = TypeEp.EPA, NumeroEp = 1, - DateCreation = new DateTime(2018, 1, 7), - DatePrevisionnelle = new DateTime(2018, 1, 6), + DateCreation = new DateTime(2020, 10, 15), + DatePrevisionnelle = new DateTime(2020, 12, 4), Obligatoire = false, - Statut = StatutEp.Signe, + Statut = StatutEp.SignatureReferent, CV = "CV.pdf", - DateSaisie = new DateTime(2018, 6, 20) + DateSaisie = new DateTime(2020, 12, 10) }; epContext.Ep.Add(ep11); - Engagement engagement1, engagement2, engagement3; + Engagement engagement1, engagement2, engagement3; // EnAttente + Engagement engagement4, engagement5, engagement6; // Respecte + Engagement engagement7, engagement8, engagement9; // NonRealisable + Engagement engagement10, engagement11, engagement12; // DateLimitePassee engagement1 = new Engagement { - Action = "Je m'engage Ă ...", - Dispositif = "interne", - Modalite = "Modalite", - DateLimite = new DateTime(2017, 7, 7), + IdEngagement = 1, + Action = "Je m'engage Ă  trouver une formation sur l'Asp.Net Core.", + Dispositif = "Demande de formation RH.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2020, 9, 1), EtatEngagement = EtatEngagement.EnAttente, RaisonNonRealisable = null, Ep = ep9 @@ -321,28 +328,147 @@ namespace EPAServeur.Context engagement2 = new Engagement { - Action = "Je m'engage Ă  faire...", - Dispositif = "externe", - Modalite = "Modalite 2", - DateLimite = new DateTime(2017, 7, 8), + IdEngagement = 2, + Action = "Je m'engage Ă  attribuer une progression salariale.", + Dispositif = "Demande d'augmentation RH.", + Modalite = "Hors temps", + DateLimite = new DateTime(2020, 9, 1), EtatEngagement = EtatEngagement.EnAttente, RaisonNonRealisable = null, - Ep = ep10 + Ep = ep9 }; epContext.Engagement.Add(engagement2); engagement3 = new Engagement { - Action = "Je m'engage Ă  faire...", - Dispositif = "externe", - Modalite = "Modalite 3", - DateLimite = new DateTime(2017, 7, 8), + IdEngagement = 3, + Action = "Je m'engage Ă  rĂ©aliser des points hebdomadaires avec l'Ă©quipe pour renforcer le lien social.", + Dispositif = "Planifier un point hebdomadaire sur Teams.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2020, 9, 1), EtatEngagement = EtatEngagement.EnAttente, - RaisonNonRealisable = "Aucune formation disponible", - Ep = ep11 + RaisonNonRealisable = null, + Ep = ep9 }; epContext.Engagement.Add(engagement3); + engagement4 = new Engagement + { + IdEngagement = 4, + Action = "Je m'engage Ă  fournir une connexion internet afin que le collaborateur puisse travailler dans de bonnes condition lorsque ce dernier est en tĂ©lĂ©travail.", + Dispositif = "Fournir un tĂ©lĂ©phone portable avec une connexion internet.", + Modalite = "Hors temps", + DateLimite = new DateTime(2020, 9, 1), + EtatEngagement = EtatEngagement.Respecte, + RaisonNonRealisable = null, + Ep = ep9 + }; + epContext.Engagement.Add(engagement4); + + engagement5 = new Engagement + { + IdEngagement = 5, + Action = "Je m'engage Ă  trouver une formation sur la mĂ©thode SCRUM.", + Dispositif = "Demande de formation RH.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2020, 12, 1), + EtatEngagement = EtatEngagement.Respecte, + RaisonNonRealisable = null, + Ep = ep10 + }; + epContext.Engagement.Add(engagement5); + + engagement6 = new Engagement + { + IdEngagement = 6, + Action = "Je m'engage Ă  rĂ©aliser un point avec le client pour amĂ©liorer l'intĂ©gration du collaborateur dans l'Ă©quipe.", + Dispositif = "Contacter le client pour planifier un rendez-vous.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2020, 10, 25), + EtatEngagement = EtatEngagement.Respecte, + RaisonNonRealisable = null, + Ep = ep10 + }; + epContext.Engagement.Add(engagement6); + + engagement7 = new Engagement + { + IdEngagement = 7, + Action = "Je m'engage Ă  attribuer 5 jours de tĂ©lĂ©travail pour le collbaorateur en dehors de la pĂ©riode Covid.", + Dispositif = "Demande RH.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2020, 12, 1), + EtatEngagement = EtatEngagement.NonRealisable, + RaisonNonRealisable = "L'accord du tĂ©lĂ©travail ne permet pas d'avoir 5 jours de travail pour le Groupe 1.", + Ep = ep10 + }; + epContext.Engagement.Add(engagement7); + + engagement8 = new Engagement + { + IdEngagement = 8, + Action = "Je m'engage Ă  attribuer 5 jours de congĂ©s supplĂ©mentaire.", + Dispositif = "Demande RH.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2020, 12, 1), + EtatEngagement = EtatEngagement.NonRealisable, + RaisonNonRealisable = "On ne peut pas donner plus de jours de congĂ©s que le nombre de droits que le salariĂ© a cotisĂ©.", + Ep = ep10 + }; + epContext.Engagement.Add(engagement8); + + engagement9 = new Engagement + { + IdEngagement = 9, + Action = "Je m'engage Ă  augmenter le salaire mensuel du collaborateur de 1000 euros.", + Dispositif = "Demande RH.", + Modalite = "Hors temps", + DateLimite = new DateTime(2021, 1, 31), + EtatEngagement = EtatEngagement.NonRealisable, + RaisonNonRealisable = "La demande d'augmentation dĂ©passe le crĂ©dit budgĂ©taire.", + Ep = ep11 + }; + epContext.Engagement.Add(engagement9); + + engagement10 = new Engagement + { + IdEngagement = 10, + Action = "Je m'engage Ă  interdire le client de conctacter le collaborateur en dehors du temps de travail.", + Dispositif = "Contacter le client pour planifier un rendez-vous.", + Modalite = "Hors temps", + DateLimite = new DateTime(2021, 1, 31), + EtatEngagement = EtatEngagement.DateLimitePassee, + RaisonNonRealisable = "La date limite pour respecter l'engagement est passĂ©e.", + Ep = ep11 + }; + epContext.Engagement.Add(engagement10); + + engagement11 = new Engagement + { + IdEngagement = 11, + Action = "Je m'engage Ă  trouver une formation sur le Cobol.", + Dispositif = "Demande de formation auprès des RH.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2021, 1, 31), + EtatEngagement = EtatEngagement.DateLimitePassee, + RaisonNonRealisable = "La date limite pour respecter l'engagement est passĂ©e.", + Ep = ep11 + }; + epContext.Engagement.Add(engagement11); + + engagement12 = new Engagement + { + IdEngagement = 12, + Action = "Je m'engage Ă  fournir une disque dur externe au collaborateur.", + Dispositif = "Demande de matĂ©riel auprès des RH.", + Modalite = "Sur temps de travail", + DateLimite = new DateTime(2021, 1, 31), + EtatEngagement = EtatEngagement.DateLimitePassee, + RaisonNonRealisable = "La date limite pour respecter l'engagement est passĂ©e.", + Ep = ep11 + }; + epContext.Engagement.Add(engagement12); + epContext.SaveChanges(); } diff --git a/EPAServeur/Controllers/EngagementsApi.cs b/EPAServeur/Controllers/EngagementsApi.cs index 95ba16a..0408661 100644 --- a/EPAServeur/Controllers/EngagementsApi.cs +++ b/EPAServeur/Controllers/EngagementsApi.cs @@ -19,6 +19,16 @@ using IO.Swagger.Security; using Microsoft.AspNetCore.Authorization; using IO.Swagger.DTO; using IO.Swagger.Enum; +using EPAServeur.Attributes; +using EPAServeur.IServices; +using Microsoft.Extensions.Logging; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Extensions.Hosting; +using Microsoft.AspNetCore.Http; +using System.Threading.Tasks; +using EPAServeur.Exceptions; +using Microsoft.EntityFrameworkCore; +using Microsoft.AspNetCore.Authentication.JwtBearer; namespace IO.Swagger.Controllers { @@ -28,12 +38,23 @@ namespace IO.Swagger.Controllers [ApiController] public class EngagementsApiController : ControllerBase { + private readonly IEngagementService engagementService; + private readonly ILogger logger; + private readonly IWebHostEnvironment env; + + public EngagementsApiController(IEngagementService _engagementService, ILogger _logger, IWebHostEnvironment _env) + { + engagementService = _engagementService; + logger = _logger; + env = _env; + } + /// /// /// /// RĂ©cupĂ©rer la liste des engagements. - /// Etats de l'engagement /// liste des ids des BU auxquelles les donnĂ©es sont rattachĂ©es + /// Etats de l'engagement /// 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 @@ -45,41 +66,49 @@ namespace IO.Swagger.Controllers /// Une erreur est survenue sur le serveur [HttpGet] [Route("/api/engagements")] - [Authorize(AuthenticationSchemes = BearerAuthenticationHandler.SchemeName)] + [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme, Roles = "RH")] [ValidateModelState] [SwaggerOperation("GetEngagements")] [SwaggerResponse(statusCode: 200, type: typeof(List), description: "OK")] [SwaggerResponse(statusCode: 401, type: typeof(ErreurDTO), description: "L'utilisateur souhaitant accĂ©der Ă  la ressource n'est pas authentifiĂ©")] [SwaggerResponse(statusCode: 403, type: typeof(ErreurDTO), description: "L’utilisateur souhaitant accĂ©der Ă  la ressource n’a pas les droits d’accès suffisants")] [SwaggerResponse(statusCode: 500, type: typeof(ErreurDTO), description: "Une erreur est survenue sur le serveur")] - public virtual IActionResult GetEngagements([FromQuery]List etatsEngagement, [FromQuery]List idBUs, [FromQuery]bool? asc, [FromQuery]int? numPage, [FromQuery][Range(5, 100)]int? parPAge, [FromQuery]string texte, [FromQuery]string tri) + public virtual async Task GetEngagements([FromQuery][CannotBeEmpty] List idBUs, [FromQuery]List etatsEngagement, [FromQuery]bool? asc, [FromQuery]int? numPage, [FromQuery][Range(5, 100)]int? parPAge, [FromQuery]string texte, [FromQuery]string tri) { - //TODO: Uncomment the next line to return response 200 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(200, default(List)); + if (env.IsDevelopment()) + logger.LogInformation("RĂ©cupĂ©ration de la liste des engagements."); - //TODO: Uncomment the next line to return response 401 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(401, default(ErreurDTO)); + IEnumerable engagements; - //TODO: Uncomment the next line to return response 403 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(403, default(ErreurDTO)); + try + { + engagements = await engagementService.GetEngagementsAsync(idBUs, etatsEngagement, asc, numPage, parPAge, texte, tri); + } + catch (Exception e) + { + logger.LogError(e.Message); - //TODO: Uncomment the next line to return response 500 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(500, default(ErreurDTO)); - string exampleJson = null; - exampleJson = "[ {\n \"action\" : \"action\",\n \"id\" : 4,\n \"dispositif\" : \"dispositif\",\n \"modalite\" : \"modalite\",\n \"dateLimite\" : \"2000-01-23T04:56:07.000+00:00\",\n \"etatEngagement\" : \"EnAttente\",\n \"raisonNonRealisable\" : \"raisonNonRealisable\"\n}, {\n \"action\" : \"action\",\n \"id\" : 4,\n \"dispositif\" : \"dispositif\",\n \"modalite\" : \"modalite\",\n \"dateLimite\" : \"2000-01-23T04:56:07.000+00:00\",\n \"etatEngagement\" : \"EnAttente\",\n \"raisonNonRealisable\" : \"raisonNonRealisable\"\n} ]"; + ErreurDTO erreur = new ErreurDTO() + { + Code = StatusCodes.Status500InternalServerError, + Message = "Une erreur inconnue est survenue sur le serveur." + }; - var example = exampleJson != null - ? JsonConvert.DeserializeObject>(exampleJson) - : default(List); //TODO: Change the data returned - return new ObjectResult(example); + return StatusCode(erreur.Code.Value, erreur); + } + + if (env.IsDevelopment()) + logger.LogInformation("Liste des engagements rĂ©cupĂ©rĂ©e."); + + return Ok(engagements); } /// /// /// /// RĂ©cupĂ©rer le nombre total d’engagements. - /// Etats de l'engagement /// liste des ids des BU auxquelles les donnĂ©es sont rattachĂ©es + /// Etats de l'engagement /// 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 @@ -91,33 +120,41 @@ namespace IO.Swagger.Controllers /// Une erreur est survenue sur le serveur [HttpGet] [Route("/api/engagements/count")] - [Authorize(AuthenticationSchemes = BearerAuthenticationHandler.SchemeName)] + [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme, Roles = "RH")] [ValidateModelState] [SwaggerOperation("GetEngagementsCount")] [SwaggerResponse(statusCode: 200, type: typeof(long?), description: "OK")] [SwaggerResponse(statusCode: 401, type: typeof(ErreurDTO), description: "L'utilisateur souhaitant accĂ©der Ă  la ressource n'est pas authentifiĂ©")] [SwaggerResponse(statusCode: 403, type: typeof(ErreurDTO), description: "L’utilisateur souhaitant accĂ©der Ă  la ressource n’a pas les droits d’accès suffisants")] [SwaggerResponse(statusCode: 500, type: typeof(ErreurDTO), description: "Une erreur est survenue sur le serveur")] - public virtual IActionResult GetEngagementsCount([FromQuery]List etatsEngagement, [FromQuery]List idBUs, [FromQuery]bool? asc, [FromQuery]int? numPage, [FromQuery][Range(5, 100)]int? parPAge, [FromQuery]string texte, [FromQuery]string tri) + public virtual async Task GetEngagementsCount([FromQuery][CannotBeEmpty]List idBUs, [FromQuery]List etatsEngagement, [FromQuery]bool? asc, [FromQuery]int? numPage, [FromQuery][Range(5, 100)]int? parPAge, [FromQuery]string texte, [FromQuery]string tri) { - //TODO: Uncomment the next line to return response 200 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(200, default(long?)); + if (env.IsDevelopment()) + logger.LogInformation("RĂ©cupĂ©ration du nombre total d'engagements."); + + long count; - //TODO: Uncomment the next line to return response 401 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(401, default(ErreurDTO)); + try + { + count = await engagementService.GetEngagementsCountAsync(idBUs, etatsEngagement, asc, numPage, parPAge, texte, tri); + } + catch (Exception e) + { + logger.LogError(e.Message); - //TODO: Uncomment the next line to return response 403 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(403, default(ErreurDTO)); + ErreurDTO erreur = new ErreurDTO() + { + Code = StatusCodes.Status500InternalServerError, + Message = "Une erreur inconnue est survenue sur le serveur." + }; - //TODO: Uncomment the next line to return response 500 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(500, default(ErreurDTO)); - string exampleJson = null; - exampleJson = "0"; + return StatusCode(erreur.Code.Value, erreur); + } - var example = exampleJson != null - ? JsonConvert.DeserializeObject(exampleJson) - : default(long?); //TODO: Change the data returned - return new ObjectResult(example); + if (env.IsDevelopment()) + logger.LogInformation("Nombre total d'engagement rĂ©cupĂ©rĂ©."); + + return Ok(count); } /// @@ -134,7 +171,7 @@ namespace IO.Swagger.Controllers /// Une erreur est survenue sur le serveur [HttpPut] [Route("/api/engagements/{idEngagement}")] - [Authorize(AuthenticationSchemes = BearerAuthenticationHandler.SchemeName)] + [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme, Roles = "RH")] [ValidateModelState] [SwaggerOperation("UpdateEngagement")] [SwaggerResponse(statusCode: 200, type: typeof(EngagementDTO), description: "Engagement modifiĂ© avec succès")] @@ -143,32 +180,95 @@ namespace IO.Swagger.Controllers [SwaggerResponse(statusCode: 404, type: typeof(ErreurDTO), description: "La ressource n'a pas Ă©tĂ© trouvĂ©e")] [SwaggerResponse(statusCode: 415, type: typeof(ErreurDTO), description: "L’opĂ©ration ne peut pas ĂŞtre effectuĂ©e car certaines donnĂ©es sont manquantes")] [SwaggerResponse(statusCode: 500, type: typeof(ErreurDTO), description: "Une erreur est survenue sur le serveur")] - public virtual IActionResult UpdateEngagement([FromBody]EngagementDTO body, [FromRoute][Required]long? idEngagement) + public virtual async Task UpdateEngagement([FromBody]EngagementDTO body, [FromRoute][Required]long idEngagement) { - //TODO: Uncomment the next line to return response 200 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(200, default(EngagementDTO)); + if (env.IsDevelopment()) + logger.LogInformation("Mise Ă  jour de l'engagement d'id {idEngagement}.", idEngagement); + + try + { + body = await engagementService.RepondreEngagementAsync(body, idEngagement); + } + catch (EngagementInvalidException e) + { + if (env.IsDevelopment()) + logger.LogInformation(e.Message); + + ErreurDTO erreur = new ErreurDTO() + { + Code = StatusCodes.Status415UnsupportedMediaType, + Message = e.Message, + }; + + return StatusCode(erreur.Code.Value, erreur.Message); + } + catch (EngagementIncompatibleIdException e) + { + if (env.IsDevelopment()) + logger.LogInformation(e.Message); + + ErreurDTO erreur = new ErreurDTO() + { + Code = StatusCodes.Status415UnsupportedMediaType, + Message = e.Message, + }; + + return StatusCode(erreur.Code.Value, erreur.Message); + } + catch (EngagementNotFoundException e) + { + if (env.IsDevelopment()) + logger.LogInformation(e.Message); + + ErreurDTO erreur = new ErreurDTO() + { + Code = StatusCodes.Status404NotFound, + Message = e.Message + }; + + return NotFound(erreur); + } + catch (DbUpdateConcurrencyException e) + { + logger.LogError(e.Message); + + ErreurDTO erreur = new ErreurDTO() + { + Code = StatusCodes.Status500InternalServerError, + Message = string.Format("L'engagement {0} n'a pas pu ĂŞtre supprimĂ© car il est pris par une autre ressource.", idEngagement) + }; + + return StatusCode(erreur.Code.Value, erreur); + } + catch (DbUpdateException e) + { + logger.LogError(e.Message); - //TODO: Uncomment the next line to return response 401 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(401, default(ErreurDTO)); + ErreurDTO erreur = new ErreurDTO() + { + Code = StatusCodes.Status500InternalServerError, + Message = "Une erreur est survenue sur le serveur lors de la suppression de l'engagement." + }; - //TODO: Uncomment the next line to return response 403 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(403, default(ErreurDTO)); + return StatusCode(erreur.Code.Value, erreur); + } + catch (Exception e) + { + logger.LogError(e.Message); - //TODO: Uncomment the next line to return response 404 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(404, default(ErreurDTO)); + ErreurDTO erreur = new ErreurDTO() + { + Code = StatusCodes.Status500InternalServerError, + Message = "Une erreur inconnue est survenue sur le serveur." + }; - //TODO: Uncomment the next line to return response 415 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(415, default(ErreurDTO)); + return StatusCode(erreur.Code.Value, erreur); + } - //TODO: Uncomment the next line to return response 500 or use other options such as return this.NotFound(), return this.BadRequest(..), ... - // return StatusCode(500, default(ErreurDTO)); - string exampleJson = null; - exampleJson = "{\n \"action\" : \"action\",\n \"id\" : 4,\n \"dispositif\" : \"dispositif\",\n \"modalite\" : \"modalite\",\n \"dateLimite\" : \"2000-01-23T04:56:07.000+00:00\",\n \"etatEngagement\" : \"EnAttente\",\n \"raisonNonRealisable\" : \"raisonNonRealisable\"\n}"; + if (env.IsDevelopment()) + logger.LogInformation("Update effectuĂ© avec succès."); - var example = exampleJson != null - ? JsonConvert.DeserializeObject(exampleJson) - : default(EngagementDTO); //TODO: Change the data returned - return new ObjectResult(example); + return Ok(body); } } } diff --git a/EPAServeur/EPAServeur.csproj b/EPAServeur/EPAServeur.csproj index 6f38212..a72dab4 100644 --- a/EPAServeur/EPAServeur.csproj +++ b/EPAServeur/EPAServeur.csproj @@ -7,10 +7,10 @@ + - diff --git a/EPAServeur/Enum/StatutEp.cs b/EPAServeur/Enum/StatutEp.cs index 6f95570..4c93d06 100644 --- a/EPAServeur/Enum/StatutEp.cs +++ b/EPAServeur/Enum/StatutEp.cs @@ -39,7 +39,7 @@ namespace IO.Swagger.Enum [EnumMember(Value = "DatesProposees")] DatesProposees = 3, /// - /// Indique qu’il s’agit d’un EPS + /// Le collaborateur a choisi une date, il ne reste plus qu'Ă  attendre l'entretien /// [EnumMember(Value = "AttenteEntretien")] AttenteEntretien = 4, diff --git a/EPAServeur/IServices/IEngagementService.cs b/EPAServeur/IServices/IEngagementService.cs index bc94629..3d22f92 100644 --- a/EPAServeur/IServices/IEngagementService.cs +++ b/EPAServeur/IServices/IEngagementService.cs @@ -1,5 +1,6 @@ using EPAServeur.Context; using IO.Swagger.DTO; +using IO.Swagger.Enum; using IO.Swagger.ModelCollaborateur; using System; using System.Collections.Generic; @@ -10,16 +11,8 @@ namespace EPAServeur.IServices { public interface IEngagementService { - - IEnumerable GetEngagements(bool? asc, int? numPage, int? parPAge, string texte, string tri); - Task> GetEngagementsAsync(bool? asc, int? numPage, int? parPAge, string texte, string tri); - IEnumerable GetEngagementsEnAttente(bool? asc, int? numPage, int? parPAge, string texte, string tri); - Task> GetEngagementsEnAttenteAsync(bool? asc, int? numPage, int? parPAge, string texte, string tri); - IEnumerable GetEngagementsRepondus(bool? asc, int? numPage, int? parPAge, string texte, string tri); - Task> GetEngagementsRepondusAsync(bool? asc, int? numPage, int? parPAge, string texte, string tri); - - EngagementDTO RepondreEngagement(EngagementDTO engagement, long? idEngagement); - Task RepondreEngagementAsync(EngagementDTO engagement, long? idEngagement); - + Task> GetEngagementsAsync(List idBUs, List etatsEngagement, bool? asc, int? numPage, int? parPage, string texte, string tri); + Task GetEngagementsCountAsync(List idBUs, List etatsEngagement, bool? asc, int? numPage, int? parPage, string texte, string tri); + Task RepondreEngagementAsync(EngagementDTO engagement, long idEngagement); } } diff --git a/EPAServeur/Services/EngagementService.cs b/EPAServeur/Services/EngagementService.cs index b5f6a69..ad750a5 100644 --- a/EPAServeur/Services/EngagementService.cs +++ b/EPAServeur/Services/EngagementService.cs @@ -2,15 +2,11 @@ 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 IO.Swagger.ModelCollaborateur; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Threading.Tasks; @@ -20,9 +16,42 @@ namespace EPAServeur.Services { #region Variables + + /// + /// Accès et gestion de la base de donnĂ©es + /// private readonly EpContext epContext; + + /// + /// Accès et service collaborateur + /// private readonly ICollaborateurService collaborateurService; - private readonly IReferentEPService referentService; + + /// + /// 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 @@ -31,260 +60,270 @@ namespace EPAServeur.Services /// Constructeur de la classe EngagementService /// /// - public EngagementService(EpContext _epContext, ICollaborateurService _collaborateurService, IReferentEPService _referentService) + public EngagementService(EpContext _epContext, ICollaborateurService _collaborateurService) { epContext = _epContext; collaborateurService = _collaborateurService; - referentService = _referentService; } #endregion #region MĂ©thodes Service - public IEnumerable GetEngagements(bool? asc, int? numPage, int? parPAge, string texte, string tri) + /// + /// RĂ©cupĂ©rer la liste des engagements de manière asynchrone + /// + /// + /// + /// + /// + /// + /// + /// + /// + public async Task> GetEngagementsAsync(List idBUs, List etatsEngagement, bool? asc, int? numPage, int? parPage, string texte, string tri) { + IQueryable query; IEnumerable engagements; + IEnumerable engagementDTOs; + IEnumerable collaborateurDTOs; - if (texte == null) - texte = ""; - else - texte = texte.ToLower(); - - int skip = (numPage.Value - 1) * parPAge.Value; - int take = parPAge.Value; + 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 = epContext.Engagement.Include(engagement => engagement.Ep).Skip(skip).Take(take); + engagements = await query.ToListAsync(); - if (engagements == null || engagements.Count() == 0) - return new List(); + collaborateurDTOs = await GetCollaborateurDTOs(engagements); - var engagementDTOs = engagements.Where(engagement => engagement.Modalite.ToLower().Contains(texte)).Select(engagement => GetEngagementDTO(engagement)); + engagementDTOs = engagements.Select(engagement => GetEngagementDTO(engagement, collaborateurDTOs)); return engagementDTOs; } - public async Task> GetEngagementsAsync(bool? asc, int? numPage, int? parPAge, string texte, string tri) + public async Task GetEngagementsCountAsync(List idBUs, List etatsEngagement, bool? asc, int? numPage, int? parPage, string texte, string tri) { - IEnumerable engagements; - - if (texte == null) - texte = ""; - else - texte = texte.ToLower(); - - int skip = (numPage.Value - 1) * parPAge.Value; - int take = parPAge.Value; - - engagements = await epContext.Engagement.Include(engagement => engagement.Ep).Skip(skip).Take(take).ToListAsync(); + IQueryable query; + long count; - if (engagements == null || engagements.Count() == 0) - return new List(); + 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); - var engagementDTOs = engagements.Where(engagement => engagement.Modalite.ToLower().Contains(texte)).Select(engagement => GetEngagementDTOAsync(engagement)); - var results = await Task.WhenAll(engagementDTOs); + count = await query.CountAsync(); - return results; + return count; } - public IEnumerable GetEngagementsEnAttente(bool? asc, int? numPage, int? parPAge, string texte, string tri) + /// + /// Donner une rĂ©ponse Ă  un engagement de manière asynchrone + /// + /// + /// + /// + public async Task RepondreEngagementAsync(EngagementDTO engagementDTO, long idEngagement) { - IEnumerable engagements; - - if (texte == null) - texte = ""; - else - texte = texte.ToLower(); - - int skip = (numPage.Value - 1) * parPAge.Value; - int take = parPAge.Value; + IEnumerable collaborateurDTOs; + Engagement engagement; - engagements = epContext.Engagement.Include(engagement => engagement.Ep).Where(engagement => engagement.EtatEngagement == EtatEngagement.EnAttente).Skip(skip).Take(take).ToList(); + IsEngagementValide(engagementDTO); - if (engagements == null || engagements.Count() == 0) - return new List(); + 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."); - var engagementDTOs = engagements.Where(engagement => engagement.Modalite.ToLower().Contains(texte)).Select(engagement => GetEngagementDTO(engagement)); - - return engagementDTOs; - } + engagement = await epContext.Engagement.Include(engagement => engagement.Ep).FirstOrDefaultAsync(engagement => engagement.IdEngagement == idEngagement); - public async Task> GetEngagementsEnAttenteAsync(bool? asc, int? numPage, int? parPAge, string texte, string tri) - { - IEnumerable engagements; - - if (texte == null) - texte = ""; - else - texte = texte.ToLower(); - - int skip = (numPage.Value - 1) * parPAge.Value; - int take = parPAge.Value; + if (engagement == null) + throw new EngagementNotFoundException(); - engagements = await epContext.Engagement.Include(engagement => engagement.Ep).Where(engagement => engagement.EtatEngagement == EtatEngagement.EnAttente).Skip(skip).Take(take).ToListAsync(); + collaborateurDTOs = await GetCollaborateurDTOs(engagement); - if (engagements == null || engagements.Count() == 0) - return new List(); + engagement = SetReponseEngagement(engagement, engagementDTO); - var engagementDTOs = engagements.Where(engagement => engagement.Modalite.ToLower().Contains(texte)).Select(engagement => GetEngagementDTOAsync(engagement)); - var results = await Task.WhenAll(engagementDTOs); + await epContext.SaveChangesAsync(); - return results; + return GetEngagementDTO(engagement, collaborateurDTOs); } - public IEnumerable GetEngagementsRepondus(bool? asc, int? numPage, int? parPAge, string texte, string tri) - { - IEnumerable engagements; - if (texte == null) - texte = ""; - else - texte = texte.ToLower(); + #endregion - int skip = (numPage.Value - 1) * parPAge.Value; - int take = parPAge.Value; + #region MĂ©thodes PrivĂ©e + /// + /// VĂ©rifier si un objet EngagementDTO est valide pour ajout ou mise Ă  jour + /// + /// 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. + /// + /// + 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."); - engagements = epContext.Engagement.Include(engagement => engagement.Ep).Where(engagement => engagement.EtatEngagement == EtatEngagement.Respecte && engagement.Modalite.ToLower().Contains(texte)).Skip(skip).Take(take); + // 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."); - if (engagements == null || engagements.Count() == 0) - return new List(); + // 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."); - var engagementDTOs = engagements.Where(engagement => engagement.Modalite.ToLower().Contains(texte)).Select(engagement => GetEngagementDTO(engagement)); + // 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."); - return engagementDTOs; - } + // 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."); - public async Task> GetEngagementsRepondusAsync(bool? asc, int? numPage, int? parPAge, string texte, string tri) - { - IEnumerable engagements; - - if (texte == null) - texte = ""; - else - texte = texte.ToLower(); - - int skip = (numPage.Value - 1) * parPAge.Value; - int take = parPAge.Value; + // 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."); - engagements = await epContext.Engagement.Include(engagement => engagement.Ep).Where(engagement => engagement.EtatEngagement == EtatEngagement.Respecte && engagement.Modalite.ToLower().Contains(texte)).Skip(skip).Take(take).ToListAsync(); + // 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."); - if (engagements == null || engagements.Count() == 0) - return new List(); - - var engagementDTOs = engagements.Where(engagement => engagement.Modalite.ToLower().Contains(texte)).Select(engagement => GetEngagementDTOAsync(engagement)); - var results = await Task.WhenAll(engagementDTOs); + // 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Ă©."); - return results; + // 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."); } /// - /// Donner une rĂ©ponse Ă  un engagement + /// Ajouter un ordonnancement croissant ou dĂ©croissant sur colonne /// - /// - /// + /// + /// /// - public EngagementDTO RepondreEngagement(EngagementDTO engagementDTO, long? idEngagement) + private IQueryable OrderByColumn(IQueryable query, bool? asc, string columnName) { + if (!asc.HasValue) + asc = defaultAsc; - if (!IsEngagementValide(engagementDTO)) - throw new EngagementInvalidException("Impossible de rĂ©pondre Ă  l'engagement, des donnĂ©es sont manquants."); - - 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Ă©."); - - if (engagementDTO == null && !engagementDTO.Id.HasValue && engagementDTO.Id.Value != idEngagement) - throw new EngagementIncompatibleIdException(); - - - Engagement engagement = epContext.Engagement.Include(engagement => engagement.Ep).FirstOrDefault(engagement => engagement.IdEngagement == idEngagement); - - if (engagement == null) - throw new EngagementNotFoundException(); + if (string.IsNullOrWhiteSpace(columnName)) + { + if (asc.Value) + return query.OrderBy(p => p.Action); - engagement.EtatEngagement = engagementDTO.EtatEngagement; + return query.OrderByDescending(p => p.Action); + } - switch (engagement.EtatEngagement) + switch (columnName.ToLower()) { - case EtatEngagement.Respecte: - engagement.EtatEngagement = engagementDTO.EtatEngagement; - engagement.RaisonNonRealisable = null; - break; - case EtatEngagement.NonRealisable: - engagement.EtatEngagement = engagementDTO.EtatEngagement; - engagement.RaisonNonRealisable = engagementDTO.RaisonNonRealisable; - break; + 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: - engagement.EtatEngagement = engagementDTO.EtatEngagement; - engagement.RaisonNonRealisable = null; - break; + if (asc.Value) + return query.OrderBy(p => p.Action); + + return query.OrderByDescending(p => p.Action); } + } - epContext.SaveChanges(); + /// + /// Ajouter un filtre pour rĂ©cupĂ©rer les engagements en fonction de plusieurs identifiants de Business Unit + /// + /// + /// + /// + /// + private IQueryable IdBUsFilter(IQueryable query, List idBUs) + { + if (idBUs == null || idBUs.Count == 0) + throw new EngagementInvalidException("Aucune Business Unit n'a Ă©tĂ© reçu."); - return GetEngagementDTO(engagement); + return query.Where(engagement => idBUs.Contains(engagement.Ep.IdBu)); } - /// - /// Donner une rĂ©ponse Ă  un engagement de manière asynchrone + /// Ajouter un filtre pour rĂ©cupĂ©rer les engagements en fonction de plusieurs Ă©tats d'engagement /// - /// - /// + /// + /// /// - public async Task RepondreEngagementAsync(EngagementDTO engagementDTO, long? idEngagement) + private IQueryable EtatsEngagementFilter(IQueryable query, List etatsEngagement) { + if (etatsEngagement == null || etatsEngagement.Count <= 0) + return query; - if (!IsEngagementValide(engagementDTO)) - throw new EngagementInvalidException("Impossible de rĂ©pondre Ă  l'engagement, des donnĂ©es sont manquants."); + return query.Where(engagement => etatsEngagement.Contains(engagement.EtatEngagement)); + } - 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Ă©."); + /// + /// Ajouter un filtre pour rĂ©cupĂ©rer les engagements en fonction d'une action + /// + /// + /// + /// + private IQueryable ActionFilter(IQueryable query, string action) + { + if (string.IsNullOrWhiteSpace(action)) + return query; + return query.Where(engagement => engagement.Action.ToLower().Contains(action.ToLower())); + } - Engagement engagement = await epContext.Engagement.Include(engagement => engagement.Ep).FirstOrDefaultAsync(engagement => engagement.IdEngagement == idEngagement); + /// + /// Ajouter une pagination + /// + /// + /// + /// + /// + private IQueryable SkipAndTake(IQueryable query, int? parPage, int? numPage) + { + int skip, take; - if (engagement == null) - throw new EngagementNotFoundException(); + if (!parPage.HasValue || parPage.Value < minParPage || parPage.Value > maxParPage) + parPage = defaultParPage; - engagement.EtatEngagement = engagementDTO.EtatEngagement; + if (!numPage.HasValue || numPage.Value <= 0) + numPage = defaultNumPage; - switch (engagement.EtatEngagement) - { - case EtatEngagement.Respecte: - engagement.EtatEngagement = engagementDTO.EtatEngagement; - engagement.RaisonNonRealisable = null; - break; - case EtatEngagement.NonRealisable: - engagement.EtatEngagement = engagementDTO.EtatEngagement; - engagement.RaisonNonRealisable = engagementDTO.RaisonNonRealisable; - break; - default: - engagement.EtatEngagement = engagementDTO.EtatEngagement; - engagement.RaisonNonRealisable = null; - break; - } - await epContext.SaveChangesAsync(); + skip = (numPage.Value - 1) * parPage.Value; + take = parPage.Value; - return await GetEngagementDTOAsync(engagement); + return query.Skip(skip).Take(take); } - #endregion - - #region MĂ©thodes PrivĂ©e - private bool IsEngagementValide(EngagementDTO engagementDTO) - { - return !(engagementDTO == null || engagementDTO.Id == null || engagementDTO.Action == null || engagementDTO.DateLimite == null || engagementDTO.Dispositif == null || engagementDTO.Modalite == null); - } - #region Object to DTO /// - /// RĂ©cupère un objet EngagementDTO en fonction d'un objet Engagement + /// RĂ©cupère un objet EngagementDTO en fonction d'un objet Engagement et d'une liste de CollaborateurDTO /// /// /// - private EngagementDTO GetEngagementDTO(Engagement engagement) + private EngagementDTO GetEngagementDTO(Engagement engagement, IEnumerable collaborateurDTOs) { EngagementDTO engagementDTO = new EngagementDTO() { @@ -295,80 +334,67 @@ namespace EPAServeur.Services Modalite = engagement.Modalite, RaisonNonRealisable = engagement.RaisonNonRealisable, EtatEngagement = engagement.EtatEngagement, - Ep = GetEpInformationDTO(engagement.Ep) + Ep = GetEpInformationDTO(engagement.Ep, collaborateurDTOs) }; return engagementDTO; } + /// - /// RĂ©cupère un objet EngagementDTO en fonction d'un objet Engagement + /// RĂ©cuperer une liste de CollaborateurDTO contenant les collaborateurs et les rĂ©fĂ©rents. Retourne null si l'engagement est null. /// - /// + /// /// - private async Task GetEngagementDTOAsync(Engagement engagement) + private async Task> GetCollaborateurDTOs(Engagement engagement) { - 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 = await GetEpInformationDTOAsync(engagement.Ep) - }; + List guids = new List(); - return engagementDTO; + guids.Add((Guid?)engagement.Ep.IdCollaborateur); + guids.Add(engagement.Ep.IdReferent); + + return await collaborateurService.GetCollaborateurDTOsAsync(guids); ; } /// - /// RĂ©cupère un objet EpInformationDTO en fonction d'un objet Ep + /// RĂ©cuperer une liste de CollaborateurDTO contenant les collaborateurs et les rĂ©fĂ©rents. Retourne null s'il n'y a aucun engagement. /// - /// + /// /// - private EpInformationDTO GetEpInformationDTO(Ep ep) + private async Task> GetCollaborateurDTOs(IEnumerable engagements) { - EpInformationDTO epInformationDTO = new EpInformationDTO() - { - Id = ep.IdEP, - Type = ep.TypeEP, - Statut = ep.Statut, - DatePrevisionnelle = ep.DatePrevisionnelle, - Obligatoire = ep.Obligatoire, - //Collaborateur = collaborateurService.GetCollaborateurById(ep.IdCollaborateur), - //Referent = referentService.GetReferentById(ep.IdReferent) - //Ajouter la date de disponibilitĂ© - }; + if (!engagements.Any()) + return null; - return epInformationDTO; + List guids = engagements.SelectMany(engagement => new[] { (Guid?)engagement.Ep.IdCollaborateur, engagement.Ep.IdReferent }).ToList(); + + return await collaborateurService.GetCollaborateurDTOsAsync(guids); } /// - /// RĂ©cupère un objet EpInformationDTO en fonction d'un objet Ep + /// RĂ©cupère un objet EpInformationDTO en fonction d'un objet Ep et d'une liste de CollaborateurDTO /// /// /// - private async Task GetEpInformationDTOAsync(Ep ep) + private EpInformationDTO GetEpInformationDTO(Ep ep, IEnumerable 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 - //Ajouter la date de disponibilitĂ© + Obligatoire = ep.Obligatoire, + Collaborateur = collaborateur, + Referent = referent, }; - var collaborateur = collaborateurService.GetCollaborateurByIdAsync(ep.IdCollaborateur); - var referent = collaborateurService.GetCollaborateurByIdAsync(ep.IdReferent); - - await Task.WhenAll(collaborateur, referent); - - epInformationDTO.Collaborateur = collaborateur.Result; - epInformationDTO.Referent = referent.Result; - return epInformationDTO; } @@ -378,51 +404,31 @@ namespace EPAServeur.Services #region DTO to Object /// - /// Modifie un objet Engagement en fonction d'un objet FormationDTO + /// Modifie la rĂ©ponse d'un objet Engagement en fonction d'un objet EngagementDTO /// /// /// /// - private Engagement SetEngagement(Engagement engagement, EngagementDTO engagementDTO) + private Engagement SetReponseEngagement(Engagement engagement, EngagementDTO engagementDTO) { - engagement.Action = engagementDTO.Action; - engagement.DateLimite = engagementDTO.DateLimite.Value; - engagement.Dispositif = engagementDTO.Dispositif; - engagement.Modalite = engagementDTO.Modalite; - engagement.RaisonNonRealisable = engagementDTO.RaisonNonRealisable; engagement.EtatEngagement = engagementDTO.EtatEngagement; - engagement.Ep = GetEp(engagementDTO.Ep); - - return engagement; - } - - /// - /// RĂ©cupère un objet Ep en fonction d'un objet EpDTO - /// - /// - /// - private Ep GetEp(EpInformationDTO epInformationDTO) - { - if (epInformationDTO == null) - return null; - - Ep ep = new Ep() + switch (engagement.EtatEngagement) { - IdEP = epInformationDTO.Id.Value, - TypeEP = epInformationDTO.Type, - Statut = epInformationDTO.Statut, - DatePrevisionnelle = epInformationDTO.DatePrevisionnelle.Value, - Obligatoire = epInformationDTO.Obligatoire.Value, - IdReferent = epInformationDTO.Referent.Id.Value, - IdCollaborateur = epInformationDTO.Collaborateur.Id.Value, - // Ajouter la date de disponibilitĂ© - }; - - return ep; + 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 diff --git a/EPAServeur/Startup.cs b/EPAServeur/Startup.cs index 887dfc8..cacfb6b 100644 --- a/EPAServeur/Startup.cs +++ b/EPAServeur/Startup.cs @@ -42,7 +42,8 @@ namespace EPAServeur }); }); - services.AddControllers(); + services.AddControllers().AddNewtonsoftJson(); + services.AddAuthentication(options => {