diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ed7dd7c123262a8fa4106caad58c8e178758bbb..5f8fbbe5e6101f5d1104581af5224161e7be4ec1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ Tous les changements de ce projet seront documentés dans ce document. ## [Non livré] +- Pouvoir charger et lancer un calcul sur les opérations non IT -> [Issue3](https://gitlab-forge.din.developpement-durable.gouv.fr/pub/numeco/m4g/numecoeval/-/issues/3) +- Intégrer la durée d'usage amont et aval des équipements physiques & ajout d'un paramètre pour choisir la méthode de calcul de la durée d'usage d'un équipement physique -> [Issue5](https://gitlab-forge.din.developpement-durable.gouv.fr/pub/numeco/m4g/numecoeval/-/issues/5) +- Pouvoir inclure dans l'évaluation d'impact des informations sur la qualité des données -> [Issue4](https://gitlab-forge.din.developpement-durable.gouv.fr/pub/numeco/m4g/numecoeval/-/issues/4) + ## [1.3.0] - 2024-03-05 diff --git a/docs/DonneeEntree.plantuml b/docs/DonneeEntree.plantuml index 3c99b1cc885096047b4f106b9022c7934752ed0a..64ee36e406478db430b8b912da063022600fb289 100644 --- a/docs/DonneeEntree.plantuml +++ b/docs/DonneeEntree.plantuml @@ -13,10 +13,12 @@ LocalDate dateLot List<String> criteresDemandees ' le paramètre suivant est facultatif. Il liste les codes des étapes souhaitées dans le calcul, en cohérence avec la table ref_EtapeACV. Son absence déclenchera le caclul sur l'ensemble des étapes présentes dans la table de référence ref_EtapeACV. List<String> etapesDemandees +List<en_OperationNonIT> operationsNonIT List<en_EqP> equipementsPhysiques List<en_DC> dataCenters List<en_Messagerie> messageries List<en_Entite> entites +String dureeUsage } class en_Entite { @@ -28,6 +30,22 @@ String responsableEntite String responsableNumeriqueDurable } +'Operation Non IT +class en_OperationNonIT { +*String nomItemNonIT +Double quantite +String type +Double dureeDeVie +String localisation +'Nom de l'entité responsable du datacenter +String nomEntite +String nomSourceDonnee +' Référence au data center = en_DC.nomCourtDataCenter +- String nomCourtDatacenter +String description +Double consoElecAnnuelle +} + 'Equipement Physique class en_EqP { * String nomEquipementPhysique @@ -41,6 +59,9 @@ String paysDUtilisation String utilisateur Date dateAchat Data dateRetrait +Double dureeUsageInterne +Double dureeUsageAmont +Double dureeUsageAval Double consoElecAnnuelle Float nbJourUtiliseAn Float goTelecharge @@ -119,6 +140,7 @@ String nomSourceDonnee } en_DonneesEntree "1"--- "0-*" en_DC : peut contenir > +en_DonneesEntree "1"--- "0-*" en_OperationNonIT : peut contenir > en_DonneesEntree "1"--- "0-*" en_EqP : peut contenir > en_DonneesEntree "1"--- "0-*" en_Messagerie : peut contenir > en_DonneesEntree "1"--- "0-*" en_Entite : peut contenir > diff --git a/docs/Indicateurs.plantuml b/docs/Indicateurs.plantuml index bf16d9f5bb0525e7743c050e283fecf943c21cf3..2df5cb5f607227e2a17431d81170384cdb4cee8c 100644 --- a/docs/Indicateurs.plantuml +++ b/docs/Indicateurs.plantuml @@ -4,6 +4,8 @@ abstract class ind_Impact { 'La date du lot permet d’agréger les données provenant de différentes sources et d'en faire un suivi temporel LocalDate dateLot +'Nom du lot +String nomLot 'Date et Heure du calcul, même valeur pour tous les indicateurs créés avec le même lot d'objets d'entrées LocalDateTime dateCalcul 'Version de l'application ayant réalisé le calcul @@ -19,7 +21,7 @@ String etapeACV 'Nom du critère associé à l'indicateur String critere String source -String referentielsSources +String nomSourceDonnee 'Unite du critère String unite 'Nom de l'organisation - Metadata @@ -28,6 +30,19 @@ String nomOrganisation String nomEntite } +'Indicateurs d'empreinte environnemtale d'une opération non IT +class ind_ImpactOperationNonIT { +' Nom de l'opération non IT présente dans les données d'entrée en_OperationNonIT +String nomItemNonIT +'le type présent dans les données d'entrée (en_OperationNonIT.type) +String typeItem +'Quantité de l'item non IT associé à l'indicateur +Integer quantite +'Impact unitaire, le champ est null en cas d'erreur lors du calcul de l'indicateur +Double impactUnitaire +Double consoElecMoyenne +} + 'Indicateurs d'empreinte environnemtale d'un équipement physique class ind_ImpactEquipementPhysique { ' Nom de l'équipement physique présent dans les données d'entrée en_EqP @@ -69,14 +84,6 @@ Double impactUnitaire Double consoElecMoyenne } - -'Indicateur Impact Réseau -class ind_ImpactReseau { -' Nom de l'équipement physique ou de la VM -*String reference -Double impactUnitaire -} - 'Indicateur d'impact pour la messagerie 'Le champ etapeACV n'est pas utilisé pour cet indicateur class ind_ImpactMessagerie { @@ -91,6 +98,7 @@ Double nombreMailEmis ind_Impact <|-- "hérite de" ind_ImpactReseau ind_Impact <|-- "hérite de" ind_ImpactApplicatif +ind_Impact <|-- "hérite de" ind_ImpactOperationNonIT ind_Impact <|-- "hérite de" ind_ImpactEquipementPhysique ind_Impact <|-- "hérite de" ind_ImpactEquipementVirtuel ind_Impact <|-- "hérite de" ind_ImpactMessagerie diff --git a/docs/MoteurDeCalculG4IT_V1.1.adoc b/docs/MoteurDeCalculG4IT_V1.1.adoc index d1e1e3a38c6139745bc4677cf58b644c3732c5b3..a529f9cded3f9e22a37b086f02d51887d58b6040 100644 --- a/docs/MoteurDeCalculG4IT_V1.1.adoc +++ b/docs/MoteurDeCalculG4IT_V1.1.adoc @@ -10,6 +10,9 @@ |majeur|Avril 2023|Ouverture en Open Source |majeur|01/02/2023|Partage des équipements entre les contextes personnels et professionnels (changement règles de calculs avec le tauxUtilisation & modeUtilisation) |majeur|22/02/2023|Intégrer des nouveaux impact au référentiel(déplacements collaborateurs, bâtiments) -> Création d'une nouvelle API facteurscaracterisation +|majeur|02/05/2023|Charger et lancer un calcul sur les nouveaux impacts (réseau, déplacements, bâtiments, maintenance) -> import de nouveaux csv OperationNonIT puis création d'indicateurs associés +|majeur|17/05/2023|Inclure dans l'évaluation d'impact des informations sur la qualité des données -> ajout d'un champ qualité à l'import puis transmission de la qualité jusqu'aux indicateurs en sortie + |=== [#_documents_de_reference] @@ -29,14 +32,14 @@ l’affichage environnemental des produits de grande consommation NumEcoEval est une solution permettant, à partir de données de dimensionnement du SI et de données de références, de calculer l’empreinte environnementale d'un système d'information. Cet outil open source a été initialisé à partir des travaux de Sopra Steria [1], de l’ADEME [2], de l’INR [3], de BOAVIZTA [4] (cf.Documents de référence), avec la contribution d'IJO. Cet outil vise à déployer massivement le calcul de l'empreinte environnementale d'un système d'information au sein d'une organisation, en connectant NumEcoEval directement aux sources de données standard de celle-ci (notamment ses CMDB). -Le volume de données pouvant être important, une attention particlière a donc été apportée à la performance de l'outil et explique certains choix d'architecture (notamment l'utilisation de l'asynchronisme). +Le volume de données pouvant être important, une attention particulière a donc été apportée à la performance de l'outil et explique certains choix d'architecture (notamment l'utilisation de l'asynchronisme). == Description des principaux concepts [#_analyse_de_cycle_de_vie] === Analyse de cycle de vie -Notre approche s’inspire des méthodes d'Analyse de Cycle de Vie (ACV), cadrées par les normes ISO 14040 et 14044. Ces normes structurent l’analyse d’impact tout au long du cycle de vie d’un produit ou d'un service.L’application de ces normes à un service numérique est encore jeune mais est à ce jour l’approche la plus poussée et celle retenue par les groupes de travail liés à la règlementation (AGEC). -NumEcoEval a été conçu pour pouvoir intégrer d'autres étapes du cycle de vie des produits selon les besoins des organisations, sous réserve que les donnéées disponilbles et/ou les standards évoluent dans ce sens. +Notre approche s’inspire des méthodes d'Analyse de Cycle de Vie (ACV), cadrées par les normes ISO 14040 et 14044. Ces normes structurent l’analyse d’impact tout au long du cycle de vie d’un produit ou d'un service. L’application de ces normes à un service numérique est encore jeune mais est à ce jour l’approche la plus poussée et celle retenue par les groupes de travail liés à la règlementation (AGEC). +NumEcoEval a été conçu pour pouvoir intégrer d'autres étapes du cycle de vie des produits selon les besoins des organisations, sous réserve que les données disponilbles et/ou les standards évoluent dans ce sens. 4 étapes du cycle de vie d'un produit sont retenues actuellement : @@ -94,9 +97,9 @@ Comme indiqué dans le schéma d'architecture fonctionnel simplifié ci-dessus, [#_donnees_de_reference] ==== Données de référence -Les données de références correspondent aux données qui ne proviennent pas directement de l'organisation (<<_Organisation>>)souhaitant utiliser NumEcoEval. Ces données peuvent être issue de la littérature scientifique, de bases de données de références externes et reconnues (NegaOctet, Base IMPACT de l'ADEME, bases de données BOAVIZTA...), ou issue de travaux empiriques. Ces données doivent nécesairement être sourcées pour assurer la traçabilité des calculs. +Les données de références correspondent aux données qui ne proviennent pas directement de l'organisation (<<_Organisation>>) souhaitant utiliser NumEcoEval. Ces données peuvent être issues de la littérature scientifique, de bases de données de références externes et reconnues (NegaOctet, Base IMPACT de l'ADEME, bases de données BOAVIZTA...), ou issues de travaux empiriques. Ces données doivent nécessairement être sourcées pour assurer la traçabilité des calculs. -Le tableau suivant permet de connaitre les données de référence utilisées dans les différentes règles de calcul.Ces données seront précédées du préfixe "ref_" suivi d'une suite de lettre permettant d'identifier la table concernée. +Le tableau suivant permet de connaitre les données de référence utilisées dans les différentes règles de calcul. Ces données seront précédées du préfixe "ref_" suivi d'une suite de lettre permettant d'identifier la table concernée. exemple : |=== @@ -104,15 +107,15 @@ exemple : |ref_Critere|Précise les critères pris en charges par l'outil, leur unité et d'autres informations qui leurs sont associées. |ref_Etape|Précise les étapes du cycle de vie prises en charge par l'outil. |ref_Hypothese |Précise les hypothèses nécessaires à certains calculs des indicateurs (par exemple les données par défaut) -|ref_TypeEquipement |Précise les types d'équipements autorisés et leur durée de vie par defaut -|ref_CorrespondanceRefEqP|Donne la correspondance entre les équipements présents dans les données d'entrées et les équipements de références présents dans la table ref_impactEquipement +|ref_TypeItem |Précise les types d'items autorisés et leur durée de vie par défaut +|ref_CorrespondanceRefEqP|Donne la correspondance entre les équipements présents dans les données d'entrées et les équipements de références présents dans la table Ref_FacteurCaracterisation |ref_FacteursCaracterisation|Donne l'impact environnemental de différents items selon le critère (<<_criteres_dimpacts_environnementaux>>) et l'étape du cycle de vie (<<_analyse_de_cycle_de_vie>>). Par exemple, il peut s'agir de l'impact sur le changement climatique d'une certaine configuration de serveur à la fabrication. |=== **Pour chaque type d'objet, des endpoints de CRUD (Create/Read/Update/Delete) sont disponibles** -le format de ces références est contraint pour garantir la capacité du moteur de calul (cf.<<_moteur_de_calcul>>) à produire les indicateurs. +Le format de ces références est contraint pour garantir la capacité du moteur de calul (cf.<<_moteur_de_calcul>>) à produire les indicateurs. link:./References.plantuml[Diagramme de classe des référentiels] @@ -138,8 +141,8 @@ Elles sont uniques pour une clé donnée. .Exemple d'hypothèses : |=== -|clé|valeur|source -|dureeVieParDefaut|1| dans le cas où la durée de vie d'un type d'équipement ne serait pas renseigner on considère une hypothèse majorante d'une mise a rebut de l'équipement au bout de 1 an. +|clé|valeur|source | description +|dureeVieParDefaut|1| dans le cas où la durée de vie d'un type d'équipement ne serait pas renseignée, on considère une hypothèse majorante d'une mise a rebut de l'équipement au bout de 1 an.| |=== [#_api_donnees_dentrees] @@ -147,7 +150,7 @@ Elles sont uniques pour une clé donnée. L'API pour les données d'entrées permet d'importer des données dans le système NumEcoEval via des endpoints REST. -Toutes les informations reçues sont envoyés simultanément : +Toutes les informations reçues sont envoyées simultanément : - Au bloc Données d'entrées pour historisation des données reçues si le module est activé - Au bloc Calcul afin de produire les indicateurs issus des règles de calculs décrites dans ce document. @@ -168,14 +171,15 @@ Ce bloc est optionnel, il n'est pas nécessaire au calcul des indicateurs mais i Les données d'entrée du sytème se trouvent dans la base "Entree". Dans la spécification, les objets représentant des données d'entrées sont précédées du préfixe "en_" -et sont classées en 4 catégories : +et sont classées en 5 catégories : -* en_EqP: liste des équipements physiques (type, d'équipement) +* en_EqP: liste des équipements physiques (type d'équipement) * en_EqV : liste des équipements virtuels (vCPU, équipement physique sous jacent...) * en_DC : liste des datacenters (identification, PUE) * en_App : liste des applications +* en_OperationsNonIT: liste des opérationsNonIT (réseau, déplacements, bâtiments, maintenance) -Tous ces objets sont groupées dans un objet en_DonneesEntree avant d'être envoyé dans l'outil. +Tous ces objets sont groupés dans un objet en_DonneesEntree avant d'être envoyés dans l'outil. Dans un premier temps, il est possible d'envoyer les objets par groupes. le format de ces données d'entrée est contraint pour garantir la capacité du moteur de calul (cf.<<_moteur_de_calcul>>) à produire les indicateurs/ @@ -186,7 +190,7 @@ link:./DonneeEntree.plantuml[Diagramme de classe des entrées] Ce bloc représente le coeur de métier de la solution NumEcoEval. Il permet de produire des indicateurs en se basant sur : -* Les référentiels exposés par le bloc Références (comprenant les critères, les étapes AVC, les hypothèses,... cf. <<_donnees_de_reference>>) +* Les référentiels exposés par le bloc Références (comprenant les critères, les étapes ACV, les hypothèses,... cf. <<_donnees_de_reference>>) * Les données d'entrées reçues via un objet en_DonneesEntree : cf <<_donnees_dentrees>> Le moteur de calcul permet d'intégrer toutes les règles de calcul (<<_regles_de_calcul>>) qui se basent sur les données de références et les données d'entrées. @@ -228,20 +232,25 @@ Le bloc Indicateurs expose les points suivants : ** Exemples: *** `ref_Hypothese(dureeVieParDefaut)` correspond à utiliser l'API GET /referentiels/hypotheses?cle={cle} avec la clé `dureeVieParDefaut` (cf.<<GET_Hypotheses>>) pour obtenir l'objet ref_Hypothese correspondant -*** `ref_ImpactReseau(etape,critere,refReseau)` (cf.<<GET_ImpactsReseaux>>) correspond à utiliser l'API GET /referentiels/impactreseaux?etape={etape}&critere={critere}&reseau={refReseau} avec les paramètres `Etape`,`Critere` et `refReseau` correspondant +*** `ref_facteurCaracterisation(nom,etape,critere)` (cf.<<GET_FacteursCaracterisation>>) correspond à utiliser l'API GET /referentiels/facteursCaracterisation?nom={nomFacteurCaracterisation}&etapeacv={etapeacv}&critere={critere}& avec les paramètres `Etape`,`Critere` et `Nom` correspondants * Le "." derrière un objet (déclaré ou obtenu après une méthode d'exposition) indique l'accès à un attribut de l'objet. ** Exemples : *** `ref_Hypothese(dureeVieParDefaut).valeur` correspond au champ valeur de l'objet ref_Hypothese de clé `dureeVieParDefaut` -*** `ref_ImpactReseau(Etape,Critere,refReseau).valeur` correspond au champ valeur de l'objet ref_ImpactReseau correspondant à `Etape`,`Critere` et `refReseau` +*** `ref_facteurCaracterisation(nom,etape,critere).valeur` correspond au champ valeur de l'objet ref_FacteurCaracterisation correspondant à `Etape`,`Critere` et `Nom` -* Toutes les règles qui calculent des indicateurs l'enregistre en base de donnée grâce à la methode sauvegarder_impact(ImpactUnitaireReseau) : cf.<<sauvegarder_impact>> +* Tous les indicateurs créés sont enregistrés en base de données grâce à la méthode sauvegarder_impact(ImpactUnitaire) : cf.<<sauvegarder_impact>> [#_moteur_de_calcul] == Moteur de calcul Le déclenchement des règles présentes dans le Bloc Calcul se réalise à la soumission des calculs sur un lot donné via le endpoint POST /entrees/calculs/soumission. +Il existe 2 paramètres associés à cette requête : + +* mode : le mode de traitement, SYNC ou ASYNC (ASYNC est la valeur par défaut) +* dureeUsage : la méthode de calcul de la durée de vie des équipements physique utilisée, FIXE : la méthode de calcul de la durée de vie se base sur l'attribut 'dureeUsageInterne' de l'équipement physique ou REEL : la méthode de calcul de la durée de vie se base sur l'âge réel de l'équipement physique (dateRetrait-dateAchat) (FIXE est la valeur par défaut) + NumEcoEval lance alors les calculs des indicateurs et les sauvegarde dans la base correspondante. La cinématique globale est décrite ci-dessous : @@ -268,11 +277,11 @@ CalculDesIndicateurs(en_DonneesEntree) { initialisation d'un compteur d'impact applicatif - BOUCLE SUR CHAQUE en_EqP DE en_DonneesEntree + BOUCLE SUR CHAQUE en_EqP de en_DonneesEntree // Exécutions des règles sur les équipements physiques calculIndicateurImpactEquipementPhysique(etape, critere, en_DonneesEntree.nomOrganisation, en_EqP, en_DC, ind_ImpactEquipementPhysique) - SI en_EqP.type est un serveur (ref_TypeEquipement.serveur est vrai) + SI en_EqP.type est un serveur (ref_TypeItem.serveur est vrai) ALORS initialisation de la variable NbvCPU correspondant à la SOMME des vCPU de tous les équipements virtuels de l'équipement physique si ce dernier est renseigné ou à l'équipement physique dans le cas contraire ET initialisation de la variable stockageTotalVirtuel correspondant à la SOMME des capaciteStockage de tous les équipements virtuels de l'équipement physique si ce dernier est renseigné ou à l'équipement physique dans le cas contraire ET initialisation de la variable nbEqV correspondant au nombre de équipements virtuels de l'équipement physique si ce dernier est renseigné ou à l'équipement physique dans le cas contraire @@ -303,6 +312,11 @@ CalculDesIndicateurs(en_DonneesEntree) { FIN BOUCLE + BOUCLE SUR CHAQUE en_OpNIT de en_DonneesEntree + // Exécutions des règles sur les opérations non IT + calculIndicateurImpactOperationNonIT(etape, critere, en_DonneesEntree.nomOrganisation, en_OpNIT, ind_ImpactOperationNonIT) + FIN BOUCLE + FIN BOUCLE FIN BOUCLE @@ -327,7 +341,8 @@ Liens vers les principaux éléments de cet algorithme * <<_regles_de_calcul>> ** <<_calcul_impact_EqP_unitaire>> ** <<_calcul_impact_EqV_unitaire>> -** <<_calculImpactReseau>> +** <<_calculIndicateurImpactApplicatif>> +** <<_calcul_impact_OperationNonIT_unitaire>> ** <<_calculImpactMessagerie>> @@ -357,9 +372,10 @@ Les champs concernés sont les suivants : |=== |Nom du champ|Obligatoire|Objet Source|Objet de Sortie|Description et usage -|dateLot|Obligatoire|en_DonneesEntree|Tous les objets indicateurs|Date du lot de rattachement des données, permet de regrouper les données d'indicateurs. Définit une seule fois pour tous les objets. +|dateLot|Facultatif|en_DonneesEntree|Tous les objets indicateurs|Date du lot de rattachement des données, permet de regrouper les données d'indicateurs. Définit une seule fois pour tous les objets. |nomOrganisation|Obligatoire|en_DonneesEntree|Tous les objets indicateurs|Nom de l'organisation rattachée aux données, permet de regrouper les données d'indicateurs. Définit une seule fois pour tous les objets. |nomEntite|Facultatif|Tous les objets d'entrées|Objets indicateurs du même niveau|Nom de l'entité responsable pouvant agir sur l'objet. Elle est définie dans les données d'entrées et alimente les indicateurs associés. +|qualité|Facultatif|en_DonneesEntree|Tous les objets indicateurs|Qualité des données d'inventaire afin de connaître la précision du cadre de l'étude et les hypothèses prises. |=== @@ -372,8 +388,8 @@ le moteur de calcul produit une trace représentée par un objet d'une des class - TraceCalculImpactEquipementPhysique : la trace du calcul d'impact d'équipement physique cf. <<_calcul_impact_EqP_unitaire>> - TraceCalculImpactEquipementVirtuel : la trace du calcul d'impact d'équipement virtuel cf. <<_calcul_impact_EqV_unitaire>> +- TraceCalculOperationNonIT : la trace du calcul d'une opération non IT cf. <<_calcul_impact_OperationNonIT_unitaire>> - TraceCalculImpactMessagerie : la trace du calcul d'impact de la messagerie cf. <<_calculImpactMessagerie>> -- TraceCalculImpactReseau : la trace du calcul d'impact du réseau cf. <<_calculImpactReseau>> Tous les objets de trace de calcul possèdent un champ "formule" permettant de vérifier le calcul de l'impact. La formule se présente comme un calcul mathématique avec le nom des variables et leurs valeurs entre parenthèses. @@ -388,75 +404,111 @@ En fonction des règles concernées, des champs supplémentaires sont alimentés link:./Traces.plantuml[Diagramme de classes des objets relatifs aux traces] -[#_rg_dureevieeqp] -==== RG_DureeVieEqP : durée de vie d'un équipement physique +[#_rg_dureevieitem] +==== RG_DureeVieItem : durée de vie d'un item (équipement physique, bâtiment...) |=== |Version|Type de changement|Description |V1|création|Initialisation de la règle à dire d'expert |=== -La durée de vie d'un équipement détermine la manière dont est amortie l'impact de sa fabrication. -Elle est exprimée en année et autorise les décimales. +La durée de vie d'un item détermine la manière dont est amortie l'impact de sa fabrication. +Elle est exprimée en années et autorise les décimales. |=== |parametre|entree/sortie|Description -|equipementPhysique|entrée|L'équipement physique dont on cherche à calculer la durée de Vie -|dureeVieEqP|sortie|La durée de vie de l'équipement physique +|item|entrée|L'item dont on cherche à calculer la durée de vie +|dureeVieItem|sortie|La durée de vie de l'item |=== [pseudocode] ---- -Règle RG_DureeVieEqP(equipementPhysique,dureeVieEqP) { - - 'dans le cas où il est possible de calculer l'age réel de l'équipement, ce dernier fait foi - SI equipementPhysique.DateAchat est correcte et renseignée ET equipementPhysique.DateRetrait est correcte et renseignée +Règle RG_DureeVieItem(equipementPhysique) { + + SI methodeDureeUsage=="REEL" ALORS - SI (equipementPhysique.DateRetrait - equipementPhysique.DateAchat) < 1 + 'dans le cas où il est possible de calculer l'age réel de l'item, ce dernier fait foi + SI equipementPhysique.DateAchat est correcte et renseignée ET equipementPhysique.DateRetrait est correcte et renseignée + ALORS + SI ((equipementPhysique.DateRetrait - equipementPhysique.DateAchat) / 365 + equipementPhysique.dureeUsageAmont + equipementPhysique.dureeUsageAval < 1) + ' si la durée de vie totale de l'équipement est inférieure à 1 an, on la fixe à 1 an car : + ' comme impact = facteurCaracterisation/dureeDeVie, si la dureeDeVie est inférieure à 1, on prendrait + de 100% de l'impact de l'équipement pour sa première année ce qui n'est pas logique + ALORS RENVOYER 1 + SINON RENVOYER (((equipementPhysique.DateRetrait - equipementPhysique.DateAchat) / 365) + equipementPhysique.DureeUsageAmont + equipementPhysique.DureeUsageAval) + 'dans le cas où seul la date d'achat est disponible, la règle du "Pseudo-amortissement" prévaut (impact de 100% sur l'année d'achat, 50% l'année 2, 33% l'année 3, etc... ) + SINON SI equipementPhysique.DateAchat est correcte et equipementPhysique.DateRetrait non reseignée + SI ((equipementPhysique.DateRetrait - date du jour) / 365 + equipementPhysique.dureeUsageAmont + equipementPhysique.dureeUsageAval < 1) + ALORS RENVOYER 1 + SINON RENVOYER (((equipementPhysique.DateAchat - date du jour) / 365) + equipementPhysique.DureeUsageAmont + equipementPhysique.DureeUsageAval) + 'dans les autres cas, une durée de vie moyenne de l'équipement est déduite + SINON + SI (RG_DureeVieItem_Defaut(equipementPhysique) + equipementPhysique.DureeUsageAmont + equipementPhysique.DureeUsageAval < 1) + ALORS RENVOYER 1 + SINON RENVOYER (RG_DureeVieItem_Defaut(equipementPhysique) + equipementPhysique.DureeUsageAmont + equipementPhysique.DureeUsageAval) + FIN SI + 'par défaut, la méthode de calcul de la durée de vie est la méthode "FIXE" + SINON + 'dans le cas où nous connaissons la durée d'usage interne par défaut, cette dernière fait foi + SI equipementPhysique.DureeUsageInterne est renseignée et supérieure à 0 + ALORS + SI (equipementPhysique.DureeUsageInterne + equipementPhysique.DureeUsageAmont + equipementPhysique.DureeUsageAval < 1) + ALORS RENVOYER 1 + SINON RENVOYER (equipementPhysique.DureeUsageInterne + equipementPhysique.DureeUsageAmont + equipementPhysique.DureeUsageAval) + SINON + SI (RG_DureeVieItem_Defaut(equipementPhysique) + equipementPhysique.DureeUsageAmont + equipementPhysique.DureeUsageAval < 1) + ALORS RENVOYER 1 + SINON RENVOYER (RG_DureeVieItem_Defaut(equipementPhysique) + equipementPhysique.DureeUsageAmont + equipementPhysique.DureeUsageAval) + FIN SI + FIN SI +} + +Règle RG_DureeVieItem(operationNonIT) { + + 'dans le cas où il est possible de calculer l'age réel de l'item, ce dernier fait foi + SI operationNonIT.dureeDeVie est correcte et renseignée + ALORS + SI operationNonIT.dureeDeVie < 1 ALORS RENVOYER 1 - SINON RENVOYER ((equipementPhysique.DateRetrait - equipementPhysique.DateAchat) / 365) - - 'dans le cas où seul la date d'achat est disponible, la règle du "Pseudo-amortissement" prévaut (impact de 100% sur l'année d'achat, 50% l'année 2, 33% l'année 3, etc... ) - SINON SI equipementPhysique.DateAchat est correcte et equipementPhysique.DateRetrait non reseignée - ALORS RENVOYER ((equipementPhysique.DateAchat - date du jour) / 365) - + SINON RENVOYER operationNonIT.dureeDeVie 'dans les autres cas, une durée de vie moyenne de l'équipement est déduite SINON - RENVOYER RG_DureeVieEqP_Defaut(equipementPhysique) + SI RG_DureeVieItem_Defaut(operationNonIT) < 1 + ALORS RENVOYER 1 + SINON RENVOYER RG_DureeVieItem_Defaut(operationNonIT) FIN SI } ---- -cf.<<_rg_dureevieeqp_defaut>> +cf.<<_rg_dureevieitem_defaut>> -[#_rg_dureevieeqp_defaut] -==== RG_DureeVieEqP_Defaut : durée de vie des équipements par défaut +[#_rg_dureevieitem_defaut] +==== RG_DureeVieItem_Defaut : durée de vie des items par défaut |=== |Version|Type de changement|Description |V1|création|Initialisation de la règle à dire d'expert |=== -La durée de vie des équipements peut être déterminée par défaut dans le cas où la date d'acquisition ne serait pas renseignée. Elle est alors calculée sur la base suivante +La durée de vie des items peut être déterminée par défaut dans le cas où l'âge réel ne serait pas renseigné. Elle est alors calculée sur la base suivante : |=== |paramètre|entree/sortie|Description -|equipementPhysique|entrée|L'équipement physique dont on cherche à calculer la durée de Vie par défaut -|dureeVieEqP_Defaut|sortie|La durée de vie par défaut de l'équipement physique +|item|entrée|L'item dont on cherche à calculer la durée de Vie par défaut +|dureeVieItem_Defaut|sortie|La durée de vie par défaut de l'item |=== [pseudocode] ---- -Règle RG_DureeVieEqP_Defaut(equipementPhysique, dureeVieEqP_Defaut) { - 'la durée de vie par défaut des équipements est celle renseignée dans la table des types d'équipements - SI l'équipement physique en entrée est présent dans la table des références d'équipement (ref_TypeEquipement.type) - ALORS dureeVieEqP_Defaut = ref_TypeEquipement.dureeVieDefaut - 'on retient l hypothèse d'une durée de vie par défaut des équipements égale à la durée de vie des équipements enregistrée dans les hypothèses +Règle RG_DureeVieItem_Defaut(Item, dureeVieItem_Defaut) { + 'la durée de vie par défaut des items est celle renseignée dans la table des types d'items + SI l'item en entrée est présent dans la table des références d'items (si Item.type = ref_TypeItem.nom) + ALORS dureeVieItem_Defaut = ref_TypeItem.dureeVieDefaut + 'on retient l hypothèse d'une durée de vie par défaut des items égale à la durée de vie des items enregistrée dans les hypothèses SINON SI ref_Hypothese(dureeVieParDefaut) existe - ALORS dureeVieEqP_Defaut = ref_Hypothese(dureeVieParDefaut).valeur + ALORS dureeVieItem_Defaut = ref_Hypothese(dureeVieParDefaut).valeur SINON - ErrCalcul("la durée de vie par défaut de l'équipement n'a pas pu être déterminée") + ErrCalcul("la durée de vie par défaut de l'item n'a pas pu être déterminée") FIN SI } ---- @@ -469,7 +521,7 @@ Règle RG_DureeVieEqP_Defaut(equipementPhysique, dureeVieEqP_Defaut) { |V1|création|Initialisation de la règle |=== -Cette règle permet de retrouver l'équipement de référence, c'est à dire celui dont les facteurs d'impact seront utilisés afin d'évaluer l'impact de l'équipement en court de traitement. +Cette règle permet de retrouver l'équipement de référence, c'est à dire celui dont les facteurs d'impact seront utilisés afin d'évaluer l'impact de l'équipement en cours de traitement. |=== |paramètre|entree/sortie|Description @@ -484,8 +536,8 @@ Règle RG_correspondanceRefEquipement(nomOrganisation, equipement, refEquipement SI ref_CorrespondanceRefEqP(nomOrganisation, equipement.modele) existe RENVOYER refEquipementretenu = ref_CorrespondanceRefEqP(nomOrganisation, equipement.modele).refEquipementCible - SINON SI ref_TypeEquipement(equipement.type).refEquipementParDefaut existe - RENVOYER refEquipementretenu = ref_TypeEquipement(equipement.type).refEquipementParDefaut + SINON SI ref_TypeItem(equipement.type).refEquipementParDefaut existe + RENVOYER refEquipementretenu = ref_TypeItem(equipement.type).refEquipementParDefaut SINON ErrCalcul("aucune correspondance avec un équipement de référence n'a pu être déterminée") FIN SI @@ -493,9 +545,37 @@ Règle RG_correspondanceRefEquipement(nomOrganisation, equipement, refEquipement } ---- -=== Calculs d'impacts unitaires +[#_rg_correspondance_RefOperationNonIT] +==== RG Correspondance entre les opérations Non IT et leur références : + +|=== +|Version|Type de changement|Description +|V1|création|Initialisation de la règle +|=== + +Cette règle permet de retrouver l'item de référence, c'est à dire celui dont les facteurs d'impact seront utilisés afin d'évaluer l'impact de l'opération non IT en cours de traitement. + +|=== +|paramètre|entree/sortie|Description +|organisation|entrée|l'organisation en cours de traitement +|item|entrée|l'item dont on cherche la référence +|refItemParDefaut|sortie|l'item dont l'impact servira de référence +|=== + +[pseudocode] +---- +Règle RG_correspondanceRefItem(nomOrganisation, item, refItemRetenu) { + + SI ref_TypeItem(item.type).refItemParDefaut existe + RENVOYER refItemRetenu = ref_TypeItem(equipement.type).refItemParDefaut + SINON + ErrCalcul("aucune correspondance avec un item de référence n'a pu être déterminée") + FIN SI +} +---- +=== Calculs d'impacts unitaires [#_calcul_impact_EqP_unitaire] ==== Calcul impact unitaire équipement physique @@ -524,6 +604,8 @@ Cette règle permet le calcul de l'impact moyen d'un équipement physique sur un |ind_ImpactEquipementPhysique.modeUtilisation|sortie|le mode d'utilisation de l'équipement, il n'est utilisé que si le taux d'utilisation n'est pas renseigné. Les deux modes possibles sont (COPE & BYOD), les taux d'utilisation correspondants son enregistrés dans la table ref_hypotheses |ind_ImpactEquipementPhysique.unite|sortie|l'unité présente dans le référentiel correspondant au critère en cours |ind_ImpactEquipementPhysique.consoElecMoyenne|sortie|la consommation électrique déterminée par la règle suivante +|ind_ImpactEquipementPhysique.qualite|sortie|la qualité de la donnée d'inventaire + |=== [pseudocode] @@ -546,9 +628,9 @@ refEquipementRetenu = RG_correspondanceRefEquipement(nomOrganisation, equipement ind_ImpactEquipementPhysique.consoElecMoyenne = EqP.consoElecAnnuelle SINON SI 'récupération de la consommation électrique de la référence de l'équipement retenue - x Ref_ImpactEquipement(refEquipementRetenu, EtapeACV, Critere).consoElecAnMoyenne + x Ref_FacteurCaracterisation(refEquipementRetenu, EtapeACV, Critere).consoElecAnMoyenne 'enregistrement de la consommation electrique retenue - ind_ImpactEquipementPhysique.consoElecMoyenne = Ref_ImpactEquipement(refEquipementRetenu, EtapeACV, Critere).consoElecAnMoyenne + ind_ImpactEquipementPhysique.consoElecMoyenne = Ref_FacteurCaracterisation(refEquipementRetenu, EtapeACV, Critere).consoElecAnMoyenne SINON ErrCalcFonc("donnée de consommation electrique manquante") Arret du calcul @@ -565,9 +647,10 @@ refEquipementRetenu = RG_correspondanceRefEquipement(nomOrganisation, equipement Arret du calcul FIN SI - x ref_MixElec(PaysDUtilisation = en_DC(NomCourtDatacenter).localisation).valeur + x ref_FacteurCaracterisation(EtapeACV, Critere, Categorie=electricity-mix, Localisation = en_DC(NomCourtDatacenter).localisation).valeur SINON - x ref_MixElec(PaysDUtilisation = EqP.PaysDUtilisation).valeur + x ref_FacteurCaracterisation(EtapeACV, Critere, Categorie=electricity-mix, Localisation = EqP.PaysDUtilisation).valeur + FIN SI SI EqP.tauxUtilisation est renseigné @@ -602,9 +685,9 @@ refEquipementRetenu = RG_correspondanceRefEquipement(nomOrganisation, equipement FIN SI 'récupération de l'impact pour le critère et l'étape ACV en cours, de la référence de l'équipement retenue - x Ref_ImpactEquipement(refEquipementretenu, EtapeACV, Critere).value + x Ref_FacteurCaracterisation(refEquipementretenu, EtapeACV, Critere).valeur - / RG_DureeVieEqP + / RG_DureeVieItem_Defaut(equipementPhysique) 'conso electrique retenue est null ind_ImpactEquipementPhysique.consoElecMoyenne = null @@ -621,14 +704,14 @@ EqP.quantité = 1 x en_EqP.ConsoElecAnMoyenne= 1000 kWh x en_EqP.tauxUtilisation = 0,85 x en_DC(NomCourtDatacenter = "googleCloud").PUE = 1,13 -x ref_MixElec("France","Changement Climatique").valeur = 0,0813225 +x ref_FacteurCaracterisation("Changement Climatique", "FABRICATION", Categorie=electricity-mix, Localisation = "France").valeur = 0,0813225 ImpactUnitaireEqP = 78,11 kg CO2eq /an ==== [#_calcul_impact_EqV_unitaire] -==== Calcul d'impact d'une machine virtuel +==== Calcul d'impact d'une machine virtuelle |=== |Version|Type de changement|Description @@ -654,7 +737,9 @@ L'impact alloué à la machine virtuelle correspond à une part de l'impact de l |ind_ImpactEquipementVirtuel.cluster|sortie|le cluster présent dans les données d'entrée pour cette équipements virtuels |ind_ImpactEquipementVirtuel.impactUnitaire|sortie|l'impact calculé pour le critère et l'étape ACV |ind_ImpactEquipementVirtuel.unite|sortie|l'unité présente dans le référentiel correspondant au critère en cours -|ind_ImpactEquipementVirtuel.consoElecMoyenne|sortie|la consommation électrique renseignée en entrée +|ind_ImpactEquipementVirtuel.consoElecMoyenne|sortie|la consommation électrique renseignée en entrée +|ind_ImpactEquipementVirtuel.qualite|sortie|la qualité de la donnée d'inventaire + |=== @@ -711,61 +796,116 @@ Il est calculé *directement dans le moteur de calcul* <<_moteur_de_calcul>> et |ind_ImpactApplicatif.sousDomaine|sortie|en_App.sousDomaine |ind_ImpactApplicatif.unite|sortie|l'unité présente dans le référentiel correspondant au critère en cours |ind_ImpactApplicatif.consoElecMoyenne|sortie|la consomation électrique calculée (correspondant à la somme des consommations éléctriques des équipements virtuels sous-jacentes) -|=== +|ind_ImpactApplicatif.qualite|sortie|la qualité de la donnée d'inventaire +|=== -[#_calculImpactReseau] -==== Calcul impact lié à la sollicitation du réseau +[#_calcul_impact_OperationNonIT_unitaire] +==== Calcul impact unitaire d'une opérationNonIT |=== -|version|type de changement|description +|Version|Type de changement|Description |V1|création|Initialisation de la règle à dire d'expert |=== -*Note importante* : cette règle de calcul ne fait pas l'objet d'un consensus -Cette règle permet le calcul de l'impact lié à la sollicitation des différents type de réseaux permettant l'interconnexion des utilisateurs et des équipements. Il peut s'agir de flux internet mais on peut aussi considérer les données transitant entre deux sites par exemple client via une liaison louée par exemple, ou même au sein d'un datacenter. +Cette règle permet le calcul de l'impact moyen d'une opération Non IT sur une année. Elle possède 3 paramètres : l'opération/l'item dont on cherche à déterminer l'impact, l'étapeACV qui permet de déterminer quelle étape du cycle de vie de l'item est regardée et le critère d'impact que l'on souhaite extraire. |=== |parametre|entree/sortie|Description -|equipementPhysique|entrée|l'équipement physique pour lequel l'impact réseau est calculé -|critere|entrée|le critere dont on cherche à calculer la durée de Vie par defaut -|etapeACV|entrée|l'étape ACV dont on cherche à calculer la durée de Vie par defaut -|ind_ImpactReseau.reference|sortie|type d'impact réseau -|ind_ImpactReseau.ImpactUnitaire|sortie|impact calculé -|ind_ImpactReseau.critere|sortie|critere calculé -|ind_ImpactReseau.etapeACV|sortie|etape ACV calculé -|ind_ImpactReseau.unite|sortie|l'unité présente dans le référentiel correspondant au critere en cours +|critere|entrée|le critere dont on cherche à calculer la durée de Vie par défaut +|etapeACV|entrée|l'étape ACV dont on cherche à calculer la durée de Vie par défaut +|nomOrganisation|entrée|le nom de l'organisation en cours de traitement +|operationNonIT|entrée|l'opération non IT dont on cherche à calculer l'impact environnemental +|ind_ImpactOperationNonIT.nomItemNonIT|sortie|le nom de l'item dont on a calculé l'impact +|ind_ImpactOperationNonIT.critere|sortie|le critere calculé +|ind_ImpactOperationNonIT.etapeACV|sortie|l'étape ACV calculée +|ind_ImpactOperationNonIT.type|sortie|le type d'item +|ind_ImpactOperationNonIT.impactUnitaire|sortie|l'impact calculé pour le critère et l'étape ACV, vaut null en cas d'erreur +|ind_ImpactOperationNonIT.quantite|sortie|la quantité d'items +|ind_ImpactOperationNonIT.unite|sortie|l'unité présente dans le référentiel correspondant au critère en cours +|ind_ImpactOperationNonIT.consoElecMoyenne|sortie|la consommation électrique +|ind_ImpactOperationNonIT.qualite|sortie|la qualité de la donnée d'inventaire |=== [pseudocode] ---- -Règle calculImpactReseau(equipementPhysique, critere, etape, ind_ImpactReseau) { - - SI equipementPhysique.goTelecharge est renseigné ET ref_ImpactReseau(etape, critere, equipementPhysique) existe - - ALORS - - impactReseau = - equipementPhysique.goTelecharge - x ref_ImpactReseau(etape, critere, equipementPhysique).valeur +soit en_OperatioNonIT(Operation) = OpNIT + +Règle calculIndicateurImpactOperationNonIT(critere, etape, nomOrganisation, OpNIT, ind_ImpactOperationNonIT) { + + 'Récupération de la correspondance de refItem + refItemRetenu = RG_correspondanceRefOperationNonIT(nomOrganisation, OpNIT) + ind_ImpactOperationNonIT(Item, EtapeACV, Critere) = + SI OpNIT.categorie = "RESEAU_MOBILE" OU "RESEAU_FIXE" OU "MAINTENANCE" OU "BATIMENT" + SI EtapeACV.code = "UTILISATION" + OpNIT.quantité + + SI OpNIT.consoElecAnnuelle est renseigné + x OpNIT.consoElecAnnuelle + 'enregistrement de la consommation electrique retenue + ind_ImpactOperationNonIT.consoElecMoyenne = OpNIT.consoElecAnnuelle + SINON SI + 'récupération de la consommation électrique de la référence de l'équipement retenue + x Ref_FacteurCaracterisation(refItemRetenu, EtapeACV, Critere).consoElecAnMoyenne + 'enregistrement de la consommation electrique retenue + ind_ImpactOperationNonIT.consoElecMoyenne = Ref_FacteurCaracterisation(refItemRetenu, EtapeACV, Critere).consoElecAnMoyenne + SINON + ErrCalcFonc("donnée de consommation electrique manquante") + Arret du calcul + FIN SI - RENVOYER ImpactUnitaireReseau - - SINON SI ref_ImpactReseau("impactReseauMobileMoyen") n'existe pas ou ref_ImpactReseau("impactReseauMobileMoyen").valeur n'est pas renseigné + x ref_FacteurCaracterisation(EtapeACV, Critere, Categorie=electricity-mix, Localisation = OpNIT.Localisation).valeur + + SINON SI EtapeACV.code != "UTILISATION" + OpNIT.quantité + + 'récupération de l'impact pour le critère et l'étape ACV en cours, de la référence de l'item retenu + x Ref_FacteurCaracterisation(refItemRetenu, EtapeACV, Critere).valeur + + SI OpNIT.categorie = "RESEAU_FIXE" + / ref_Hypothese.valeur(CAPACITE_LIGNE_FIXE_LOCALISATION) + + SINON SI OpNIT.categorie = "BATIMENT" + / RG_DureeVieItem_Defaut(operationNonIT) + FIN SI + + SINON SI OpNIT.categorie = "DEPLACEMENT_ELECTRIQUE" OU "DEPLACEMENT_ESSENCE" OU DEPLACEMENT_HYBRIDE + 'nombre de kilomètres parcourus dans le véhicule + OpNIT.quantité - ErrCalcFonc("la référence impactReseauMobileMoyen n'existe pas") + 'récupération de la consommation moyenne pour le véhicule choisi, valeur récupérée dans ref_hypothèses + x ref_Hypothese.valeur(OpNIT.refHypothese) + SI OpNIT.categorie = "DEPLACEMENT_ELECTRIQUE" + 'récupération du mix électrique pour le critère de Fabrication et pour l'étape ACV en cours + x ref_FacteurCaracterisation.valeur(FABRICATION, Critère, mix elec, OpNIT.Localisation)) + + SINON SI OpNIT.categorie = "DEPLACEMENT_ESSENCE" + 'récupération de l'impact de la production d'essence pour le critère de Fabrication et pour l'étape ACV en cours + x ref_FacteurCaracterisation.valeur(FABRICATION, Critère, Production essence )) + + SINON SI OpNIT.categorie = "DEPLACEMENT_HYBRIDE" + 'récupération de l'impact de la production d'essence pour le critère de Fabrication et pour l'étape ACV en cours + x ref_FacteurCaracterisation.valeur(FABRICATION, Critère, Production essence )) + 'récupération du taux utile pour le calcul d'impact des véhicules hybrides, valeur récupérée dans ref_hypothèses + x ref_Hypothese.valeur('taux_vehicule_hybride') + + FIN SI FIN SI } ---- -Références: - -* ref_ImpactReseau(etape, critere, equipementPhysique) : cf.<<GET_ImpactsReseaux>> -* sauvegarder_impact(impact) : cf.<<sauvegarder_impact>> - +.Calcul de l'impact "moyen" en CO2 lié à l'utilisation d'un réseau fixe sur 1 an +==== +Item = exemple d'un réseau fixe localisé en France +OpNIT.quantité = 400 +x ref_FacteurCaracterisation(reseau-fixe, UTILISATION, Changement Climatique).ConsoElecAnMoyenne = 180 kWh +x ref_FacteurCaracterisation( UTILISATION, Changement Climatique,mixelec,France).valeur = 0.0813225 +/ ref_Hypothese(CAPACITE_LIGNE_FIXE_FR) = 2640 +ImpactUnitaireOpNIT = 2,21788 kg CO2eq /an +==== [#_calculImpactMessagerie] ==== Calcul impact lié à la Messagerie @@ -804,6 +944,7 @@ Règle calculImpactMessagerie(en_Messagerie, ref_Critere, ref_ImpactMessagerie, } ---- + == Gestion des erreurs === ErrCalcFonc @@ -812,7 +953,7 @@ Au déclenchement de ce type d'erreur, une ligne s'affiche dans les logs, avec l .Erreur de calcul de l'impact réseau ==== - "ErrCalcFonc : ImpactUnitaireReseau(equipement, etapeACV, critere) ; la référence "impactReseauMobileMoyen" n'existe pas" + "ErrCalcFonc : ImpactUnitaireOperationNonIT(item, etapeACV, critere) ; la référence "impactReseauMobileMoyen" n'existe pas" ==== === ErrCalcTech diff --git a/docs/RELEASE.md b/docs/RELEASE.md new file mode 100644 index 0000000000000000000000000000000000000000..b93d116797e6bc31cb0f1e9e0b729bbd87123767 --- /dev/null +++ b/docs/RELEASE.md @@ -0,0 +1,20 @@ +# Création de release + +Exemple avec version actuelle 1.4.0-SNAPSHOT pour faire une release 1.4.0, puis préparer la develop sur 1.5.0-SNAPSHOT + +- Créer une MR develop -> main + +- STOP PIPELINES (car non utiles ici) + +- Sur branche main: + - CHANGELOG: nouvelle release + - Maj version pom.xml <version>1.4.0</version> (un replace all permet d'aller plus vite) + - Commit + push + - STOP PIPELINES (car non utiles ici) + +- Gitlab: Code > Tags + - Créer le tag : ça va builder tout, laisser les pipelines tourner + +- Sur la branche develop, maj du pom -> 1.5.0-SNAPSHOT + - Commit + push + - Laisser les pipelines tourner diff --git a/docs/References.plantuml b/docs/References.plantuml index 7c2296aa23d9a9f9c36ae24065e1b075ee49d5a2..52d234c61d99ce24ce2a264ceba0f62bc7292bc2 100644 --- a/docs/References.plantuml +++ b/docs/References.plantuml @@ -1,23 +1,26 @@ @startuml -'les hypotheses generique regroupe les hypothèses permettant le calcul de certains indicateurs +'les hypothèses permettant le calcul de certains indicateurs class ref_Hypothese{ *String clé String valeur String source } -'liste des types d'équipements autorisés et de leur durée de vie par défaut -class ref_TypeEquipement{ +'liste des types d'items autorisés +class ref_TypeItem{ *String type +String categorie 'le booléen "serveur" permet de distinguer les équipements inclus dans le calcul de l'impact d'un serveur applicatif à l'utilisation boolean serveur 'le commentaire permet notamment de détailler les catégories équipements contenues dans un même type String commentaire Double dureeVieDefaut -' la référence de l'équipement par defaut doit exister dans la table ref_ImpactEquipement.refEquipement -String refEquipementParDefaut +' la référence de l'hypothese doit exister dans la table ref_Hypothese.cle +String refHypothese String source +' la référence de l'item par defaut doit exister dans la table ref_FacteurCaracterisation.nom +String refItemParDefaut } 'Impact environnementaux de référence @@ -51,7 +54,7 @@ String unité String description } -' étapes du cycle de vie des équipements pris en compte dans les calculs +' étapes du cycle de vie des items pris en compte dans les calculs class ref_EtapeACV { * String code String libelle diff --git a/docs/Traces.plantuml b/docs/Traces.plantuml index 6798e03448ca8487a7aafeebf3ec8c423d921855..c93a538230b5865aa6b33bae3c5dab8835e3e027 100644 --- a/docs/Traces.plantuml +++ b/docs/Traces.plantuml @@ -19,14 +19,32 @@ class TraceCalculImpactEquipementPhysique { Double valeurReferentielImpactEquipement String sourceReferentielImpactEquipement DureeDeVie dureeDeVie + String erreur +} + +class TraceCalculOperationNonIT { + String formule + ConsoElecAnMoyenne consoElecAnMoyenne + MixElectrique mixElectrique + Double valeurReferentielFacteurCaracterisation + String valeurReferentielFacteurCaracterisation + Hypothese hypothese; + DureeDeVie dureeDeVie + String erreur } class TraceCalculImpactEquipementVirtuel { String formule - boolean vCPUok - Integer vCPU - Integer nbvCPU - Integer nbVM + Integer nbEquipementsVirtuels + Integer nbTotalVCPU + Double stockageTotalVirtuel + String erreur +} + +class TraceCalculImpactApplication { + String formule + Integer nbApplications + String erreur } class TraceCalculImpactMessagerie { @@ -41,16 +59,6 @@ class TraceCalculImpactMessagerie { Double nombreMailEmisXDestinataires } -class TraceCalculImpactReseau { - String formule - String critere - String etapeACV - String sourceReferentielReseau - String equipementPhysique - String impactReseauMobileMoyen - String goTelecharge -} - ' Classes des objets associées aux calculs class ConsoElecAnMoyenne { @@ -61,7 +69,11 @@ class ConsoElecAnMoyenne { } class DureeDeVie { - Double valeur + Double valeurRetenue + private String methodeDureeUsage + private Double dureeUsageInterne + private Double dureeUsageAmont + private Double dureeUsageAval String dateAchat String dateRetrait DureeDeVieParDefaut dureeDeVieParDefaut @@ -96,11 +108,14 @@ DureeDeVie "0-1" -up- "1" TraceCalculImpactEquipementPhysique : peut contenir > MixElectrique "0-1" -up- "1" TraceCalculImpactEquipementPhysique : peut contenir > NbJourUtiliseAn "0-1" -up- "1" TraceCalculImpactEquipementPhysique : peut contenir > -DureeDeVieParDefaut "0-1" -up- "1" DureeDeVie : peut contenir > +ConsoElecAnMoyenne "0-1" -up- "1" TraceCalculOperationNonIT : peut contenir > +DureeDeVie "0-1" -up- "1" TraceCalculOperationNonIT : peut contenir > +MixElectrique "0-1" -up- "1" TraceCalculOperationNonIT : peut contenir > +DureeDeVieParDefaut "0-1" -up- "1" DureeDeVie : peut contenir > -TraceCalculImpact <|-- "hérite de" TraceCalculImpactReseau TraceCalculImpact <|-- "hérite de" TraceCalculImpactMessagerie +TraceCalculImpact <|-- "hérite de" TraceCalculOperationNonIT TraceCalculImpact <|-- "hérite de" TraceCalculImpactEquipementVirtuel TraceCalculImpact <|-- "hérite de" TraceCalculImpactEquipementPhysique diff --git a/e2e/1_load_ref.sh b/e2e/1_load_ref.sh index 36093c58c4752b8517893b58a491a250b4a8f02e..04a1b4fcac52ef1b9a375ad5e41dac06bc1275b2 100644 --- a/e2e/1_load_ref.sh +++ b/e2e/1_load_ref.sh @@ -1,7 +1,7 @@ #!/bin/bash # CONTANTS -REFERENTIELS="criteres etapes hypotheses typeEquipement correspondanceRefEquipement facteursCaracterisation" +REFERENTIELS="criteres etapes hypotheses correspondanceRefEquipement facteursCaracterisation typeItem" E2E_LOCAL_PATH=. diff --git a/e2e/2_generate_dataset.sh b/e2e/2_generate_dataset.sh index 54aac7a1f44f419535bb7cfde3ef06b235907c51..5fafb28a04e5036fe75f62f246f1c0550407e7c3 100644 --- a/e2e/2_generate_dataset.sh +++ b/e2e/2_generate_dataset.sh @@ -8,7 +8,7 @@ NB_APP_PAR_VM=${4:-2} . ./.env . ./utils.sh -# CONTANTS +# CONSTANTS NB_CSV_HORS_SRV=100 NB_CSV_SRV=100 @@ -64,6 +64,10 @@ for ((i = 1; i <= $(($NB_EQ_PH_SRV / $NB_CSV_SRV)); i++)); do done >>data/EquipementVirtuel.csv done +# *** OperationNonIT.csv *** +log "Generate input data : OperationNonIT.csv" +cp -f input_template/OperationNonIT.csv data/ + # *** Application.csv *** log "Generate input data : Application.csv" head -n1 input_template/Application.csv >data/Application.csv diff --git a/e2e/3_load_input.sh b/e2e/3_load_input.sh index 1368dc3a89bf526dacead1cd8370ee43cc705d0d..371bde950c46be8748e8dec71d9cc7e0029f5e4a 100644 --- a/e2e/3_load_input.sh +++ b/e2e/3_load_input.sh @@ -4,6 +4,8 @@ ORGANISATION=${1:-org1} NOM_LOT=$2 SCENARIO=${3:-E2E} MODE=${4:-ASYNC} +DUREE_USAGE=${5:-FIXE} + DATE_LOT=$(date +'%Y-%m-%d') . ./.env @@ -13,15 +15,16 @@ rm -f progress.log log_n "$ORGANISATION - $NOM_LOT - $DATE_LOT - Load Input - " | tee -a progress.log curl -s -XPOST "$ENTREE_URL/entrees/csv?nomLot=${NOM_LOT}&dateLot=${DATE_LOT}&nomOrganisation=${ORGANISATION}" \ - --form csvDataCenter=@data/DataCenter.csv \ - --form csvEquipementPhysique=@data/EquipementPhysique.csv \ - --form csvEquipementVirtuel=@data/EquipementVirtuel.csv \ - --form csvApplication=@data/Application.csv | tee -a progress.log -echo "" | tee -a progress.log + --form csvDataCenter=@data/DataCenter.csv \ + --form csvEquipementPhysique=@data/EquipementPhysique.csv \ + --form csvEquipementVirtuel=@data/EquipementVirtuel.csv \ + --form csvApplication=@data/Application.csv \ + --form csvOperationNonIT=@data/OperationNonIT.csv | tee -a progress.log + echo "" | tee -a progress.log sleep 2 -log_n "$ORGANISATION - $NOM_LOT - $DATE_LOT - Soumission with mode=${MODE} - " | tee -a progress.log +log_n "$ORGANISATION - $NOM_LOT - $DATE_LOT - Soumission with mode=${MODE} & duree usage=${DUREE_USAGE}" | tee -a progress.log -curl -s -XPOST "$ENTREE_URL/entrees/calculs/soumission?mode=$MODE" -d"{\"nomLot\":\"${NOM_LOT}\"}" -H "Content-Type: application/json" | tee -a progress.log +curl -s -XPOST "$ENTREE_URL/entrees/calculs/soumission?dureeUsage=$DUREE_USAGE&mode=$MODE" -d"{\"nomLot\":\"${NOM_LOT}\"}" -H "Content-Type: application/json" | tee -a progress.log echo "" | tee -a progress.log diff --git a/e2e/5_assert.sh b/e2e/5_assert.sh index 86b42ab20104dca5f01850385463a90a8ff13f5c..03c217fb5b59c128fc3858c0a25e8371217e2748 100644 --- a/e2e/5_assert.sh +++ b/e2e/5_assert.sh @@ -15,10 +15,12 @@ export_table() { if [ -d actual ]; then rm -rf actual; fi mkdir actual -export_table equipementPhysique conso_elec_moyenne,critere,etapeacv,impact_unitaire,nom_entite,nom_entite_discriminator,nom_equipement,nom_source_donnee,nom_source_donnee_discriminator,quantite,source,statut_equipement_physique,statut_indicateur,trace,type_equipement,unite,version_calcul -export_table equipementVirtuel cluster,conso_elec_moyenne,critere,etapeacv,impact_unitaire,nom_entite,nom_entite_discriminator,nom_equipement,nom_equipement_virtuel,nom_source_donnee,nom_source_donnee_discriminator,source,statut_indicateur,trace,unite,version_calcul -export_table application conso_elec_moyenne,critere,domaine,etapeacv,impact_unitaire,nom_application,nom_entite,nom_entite_discriminator,nom_equipement_physique,nom_equipement_virtuel,nom_source_donnee,nom_source_donnee_discriminator,source,sous_domaine,statut_indicateur,trace,type_environnement,unite,version_calcul +export_table equipementPhysique conso_elec_moyenne,critere,etapeacv,impact_unitaire,nom_entite,nom_entite_discriminator,nom_equipement,nom_source_donnee,nom_source_donnee_discriminator,quantite,source,statut_equipement_physique,statut_indicateur,trace,type_equipement,unite,version_calcul,qualite +export_table equipementVirtuel cluster,conso_elec_moyenne,critere,etapeacv,impact_unitaire,nom_entite,nom_entite_discriminator,nom_equipement,nom_equipement_virtuel,nom_source_donnee,nom_source_donnee_discriminator,source,statut_indicateur,trace,unite,version_calcul,qualite +export_table application conso_elec_moyenne,critere,domaine,etapeacv,impact_unitaire,nom_application,nom_entite,nom_entite_discriminator,nom_equipement_physique,nom_equipement_virtuel,nom_source_donnee,nom_source_donnee_discriminator,source,sous_domaine,statut_indicateur,trace,type_environnement,unite,version_calcul,qualite export_table reseau etapeacv,critere,source,statut_indicateur,trace,version_calcul,impact_unitaire,unite,nom_entite,nom_equipement +export_table operationNonIT conso_elec_moyenne,critere,etapeacv,impact_unitaire,nom_entite,nom_entite_discriminator,nom_item_non_it,nom_source_donnee,nom_source_donnee_discriminator,quantite,source,statut_indicateur,trace,type_item,unite,version_calcul,qualite + ALL_OK=true for file in $(ls actual/); do echo -n "Check file $file : " diff --git a/e2e/e2e.iml b/e2e/e2e.iml deleted file mode 100644 index 885ffe64a60205bdd9858b06a69d8c16c57e1497..0000000000000000000000000000000000000000 --- a/e2e/e2e.iml +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<module version="4"> - <component name="SonarLintModuleSettings"> - <option name="uniqueId" value="3533810f-e57c-45f5-bdb3-84fc26316012" /> - </component> -</module> \ No newline at end of file diff --git a/e2e/input_template/Application.csv b/e2e/input_template/Application.csv index f6d03dcd2a587361b88401bdd1d793cbcb72434c..ffc0f6105435ca31f22f2745b7c95a1b2219a135 100644 --- a/e2e/input_template/Application.csv +++ b/e2e/input_template/Application.csv @@ -1,2 +1,2 @@ -nomApplication;typeEnvironnement;nomEquipementVirtuel;nomSourceDonneeEquipementVirtuel;domaine;sousDomaine;nomEntite;nomEquipementPhysique;nomSourceDonnee -application-;##TYPE_ENV##;virtual-eq-;;Domain 1;Sub Domain 1;MY ENTERPRISE;physical-eq-srv-;; +nomApplication;typeEnvironnement;nomEquipementVirtuel;nomSourceDonneeEquipementVirtuel;domaine;sousDomaine;nomEntite;nomEquipementPhysique;nomSourceDonnee;qualite +application-;##TYPE_ENV##;virtual-eq-;;Domain 1;Sub Domain 1;MY ENTERPRISE;physical-eq-srv-;;haute diff --git a/e2e/input_template/DataCenter.csv b/e2e/input_template/DataCenter.csv index 11043f092ce8a6b463cce0b868d2cc2038f9ce12..800d506a24bcd2bc83ba31a2dd4c41935185a70b 100644 --- a/e2e/input_template/DataCenter.csv +++ b/e2e/input_template/DataCenter.csv @@ -1,8 +1,8 @@ -nomCourtDatacenter;nomLongDatacenter;pue;localisation;nomEntite; -default;Default;1.75;France;; -B1;B1;1.32;France;; -F1;F1;1.43;France;; -G1;G1;1.45;Spain;; +nomCourtDatacenter;nomLongDatacenter;pue;localisation;nomEntite;qualite +default;Default;1.75;France;;Haute +B1;B1;1.32;France;;bAsse +F1;F1;1.43;France;;Moyenne +G1;G1;1.45;Spain;;erreur X1;X1;1.42;Russia;; Y1;Y1;1.41;Germany;; Z2;Z2;1.75;France;; diff --git a/e2e/input_template/EquipementPhysique_hors_serveur.csv b/e2e/input_template/EquipementPhysique_hors_serveur.csv index f8963fae13cdaafa4a4d2a48944b3d071820a321..918baf79bc1849420c76cd23e5c73c6151ec0435 100644 --- a/e2e/input_template/EquipementPhysique_hors_serveur.csv +++ b/e2e/input_template/EquipementPhysique_hors_serveur.csv @@ -1,101 +1,101 @@ -nomEquipementPhysique;modele;quantite;nomCourtDatacenter;dateAchat;dateRetrait;type;statut;paysDUtilisation;consoElecAnnuelle;utilisateur;nomSourceDonnee;nomEntite;nbCoeur;nbJourUtiliseAn;goTelecharge;modeUtilisation;tauxUtilisation -physical-eq-001;P2719;1;;2021-03-30;2023-06-16;Monitor;In use;France;;;;MY ENTERPRISE;;365;;COPE; -physical-eq-002;P2719;2;;2021-03-30;2023-06-16;Monitor;In use;France;;;;MY ENTERPRISE;;365;;BYOD; -physical-eq-003;P2719;4;;2021-03-30;2023-06-16;Monitor;In use;France;;;;MY ENTERPRISE;;365;;COB; -physical-eq-004;HUB USB;10;;2023-04-01;2023-06-16;Consumable;Consumed;France;;;;MY ENTERPRISE;;365;;BYOD;0.1 -physical-eq-005;P2720DC;2;;2022-11-04;2023-06-16;Monitor;In stock;France;;;;MY ENTERPRISE;;365;;BYOD;12.1 -physical-eq-006;PIXEL 6;1;;2022-10-18;2023-06-16;Communication Device;Missing;France;;;;MY ENTERPRISE;;365;;;test -physical-eq-007;UP2516D;1;;2022-07-31;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;0.9 -physical-eq-008;UP2516D;2;;2022-03-10;2023-06-16;Monitor;In stock;France;;;;MY ENTERPRISE;;365;;COPE;0.6 -physical-eq-009;Unknown;3;;2021-08-09;2023-06-16;IP Router;In use;France;;;;MY ENTERPRISE;;365;;COPE;0 -physical-eq-010;Unknown;3;;2021-08-09;2023-06-16;IP Router;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-011;HP 8440p;1;;2021-08-05;2023-06-16;Personal Computer;Missing;France;;;;MY ENTERPRISE;;365;;; -physical-eq-012;HP 8440p;1;;2023-04-27;2023-06-16;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-013;HP 8470w;2;;2025-08-23;2023-06-16;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-014;OPPO A72;1;;2023-08-07;2023-06-16;Communication Device;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-015;CROSSCALL;1;;2022-08-20;2023-06-16;Communication Device;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-016;CROSSCALL;11;;2022-05-20;2023-06-16;Communication Device;In stock;France;;;;MY ENTERPRISE;;365;;; -physical-eq-017;CROSSCALL;8;;2022-05-28;2023-06-16;Communication Device;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-018;HUAWEI P9;11;;2021-01-28;2023-06-16;Communication Device;In stock;France;;;;MY ENTERPRISE;;365;;; -physical-eq-019;HUAWEI P9;4;;2022-08-18;2023-06-16;Communication Device;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-020;HUAWEI P9;1;;2023-06-18;2023-06-16;Communication Device;Missing;France;;;;MY ENTERPRISE;;365;;; -physical-eq-021;HUAWEI P9;32;;2021-01-28;2023-06-16;Communication Device;Missing;France;;;;MY ENTERPRISE;;365;;; -physical-eq-022;HUAWEI P9;9;;2024-08-18;2023-06-16;Communication Device;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-023;PRO MP242;50;;2022-06-21;2023-06-16;Monitor;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-024;SAC A DOS;534;;2023-02-18;2023-06-16;Consumable;Consumed;France;;;;MY ENTERPRISE;;365;;; -physical-eq-025;SAC A DOS;1;;2023-02-18;2023-06-16;Consumable;Missing;France;;;;MY ENTERPRISE;;365;;; -physical-eq-026;SPIDER X1;2;;2022-10-17;2023-06-16;Communication Device;In stock;France;;;;MY ENTERPRISE;;365;;; -physical-eq-027;DELL 1909W;5;;2022-11-20;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-028;DELL 1909W;1;;2021-12-20;2023-06-16;Monitor;Missing;France;;;;MY ENTERPRISE;;365;;; -physical-eq-029;DELL 1909W;14;;2025-10-17;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-030;DELL 2412M;1;;2022-12-26;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-031;DELL 2717H;19;;2021-04-08;2023-06-16;Monitor;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-032;DELL 2717H;1;;2024-11-23;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-033;DELL E7440;5;;2023-03-19;2023-06-16;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-034;DELL E7440;31;;2025-10-27;2023-06-16;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-035;DELL E7440;11;;2022-04-24;2023-06-16;Personal Computer;Missing;France;;;;MY ENTERPRISE;;365;;; -physical-eq-036;DELL E7450;2;;2022-12-21;2023-06-16;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-037;DELL E7450;14;;2025-10-31;2023-06-16;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-038;DELL E7450;6;;2022-04-22;2023-06-16;Personal Computer;Missing;France;;;;MY ENTERPRISE;;365;;; -physical-eq-039;DELL E7470;33;;2023-02-11;2023-06-16;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-040;DELL E7470;23;;2022-03-16;2023-06-16;Personal Computer;Missing;France;;;;MY ENTERPRISE;;365;;; -physical-eq-041;DELL E7470;9;;2022-03-16;2023-06-16;Personal Computer;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-042;DELL E7470;4;;2022-03-16;2023-06-16;Personal Computer;In stock;France;;;;MY ENTERPRISE;;365;;; -physical-eq-043;DELL E7470;325;;2024-09-01;2023-06-16;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-044;DELL E7470;2;;2025-03-03;2023-06-16;Personal Computer;In stock;France;;;;MY ENTERPRISE;;365;;; -physical-eq-045;DELL E7480;349;;2022-12-11;2023-06-16;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-046;DELL E7480;49;;2021-10-26;2023-06-16;Personal Computer;Missing;France;;;;MY ENTERPRISE;;365;;; -physical-eq-047;DELL E7480;18;;2021-09-25;2023-06-16;Personal Computer;In stock;France;;;;MY ENTERPRISE;;365;;; -physical-eq-048;DELL E7480;141;;2023-11-04;2023-06-16;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-049;DELL E7480;70;;2021-09-30;2023-06-16;Personal Computer;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-050;DELL E7480;1;;2025-06-03;2023-06-16;Personal Computer;Missing;France;;;;MY ENTERPRISE;;365;;; -physical-eq-051;DELL E7490;248;;2022-03-21;2023-06-16;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-052;DELL E7490;52;;2021-06-17;2023-06-16;Personal Computer;In stock;France;;;;MY ENTERPRISE;;365;;; -physical-eq-053;DELL E7490;421;;2021-06-01;2023-06-16;Personal Computer;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-054;DELL E7490;51;;2021-06-19;2023-06-16;Personal Computer;Missing;France;;;;MY ENTERPRISE;;365;;; -physical-eq-055;DELL E7490;6;;2024-04-20;2023-06-16;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-056;DELL P1911;8;;2022-07-25;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-057;DELL P1911;6;;2025-01-04;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-058;DELL P1913;4;;2022-11-02;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-059;DELL P1913;2;;2024-04-12;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-060;HUAWEI P20;1;;2021-12-24;2023-06-16;Communication Device;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-061;LENOVO M73;13;;2024-01-25;2023-06-16;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-062;LENOVO M73;13;;2022-01-25;2023-06-16;Personal Computer;In Use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-063;ANTIVOL MAC;1;;2023-01-14;2023-06-16;Consumable;Missing;France;;;;MY ENTERPRISE;;365;;; -physical-eq-064;ANTIVOL MAC;1;;2023-01-14;2023-06-16;Consumable;In stock;France;;;;MY ENTERPRISE;;365;;; -physical-eq-065;ANTIVOL MAC;10;;2023-01-14;2023-06-16;Consumable;Consumed;France;;;;MY ENTERPRISE;;365;;; -physical-eq-066;AOC U2879VF;10;;2022-11-27;2023-06-16;Monitor;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-067;DELL P2210T;1;;2022-12-29;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-068;DELL P2217H;286;;2021-03-13;2023-06-16;Monitor;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-069;DELL P2217H;1;;2021-03-13;2023-06-16;Monitor;Missing;France;;;;MY ENTERPRISE;;365;;; -physical-eq-070;DELL P2217H;5;;2022-01-14;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-071;DELL P2217H;6;;2021-03-13;2023-06-16;Monitor;In stock;France;;;;MY ENTERPRISE;;365;;; -physical-eq-072;DELL P2217H;3;;2023-10-15;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-073;DELL P2319H;1;;2022-12-19;2023-06-16;Monitor;In stock;France;;;;MY ENTERPRISE;;365;;; -physical-eq-074;DELL P2319H;49;;2022-12-19;2023-06-16;Monitor;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-075;DELL P2412H;1;;2022-03-25;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-076;DELL P2412H;1;;2025-06-01;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-077;DELL P2415Q;7;;2022-03-13;2023-06-16;Monitor;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-078;DELL P2415Q;1;;2022-03-13;2023-06-16;Monitor;In stock;France;;;;MY ENTERPRISE;;365;;; -physical-eq-079;DELL P2417H;371;;2021-03-18;2023-06-16;Monitor;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-080;DELL P2417H;7;;2022-07-16;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-081;DELL P2417H;4;;2024-07-02;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-082;DELL P2417H;5;;2021-03-18;2023-06-16;Monitor;In stock;France;;;;MY ENTERPRISE;;365;;; -physical-eq-083;DELL P2419H;11;;2021-09-01;2023-06-16;Monitor;In stock;France;;;;MY ENTERPRISE;;365;;; -physical-eq-084;DELL P2419H;11;;2022-10-18;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-085;DELL P2419H;847;;2021-09-01;2023-06-16;Monitor;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-086;DELL P2419H;1;;2021-09-01;2023-06-16;Monitor;Missing;France;;;;MY ENTERPRISE;;365;;; -physical-eq-087;DELL P2419H;32;;2024-05-15;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-088;DELL P2422H;7;;2023-04-23;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-089;DELL P2422H;2;;2023-09-30;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-090;DELL P2422H;588;;2022-09-25;2023-06-16;Monitor;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-091;DELL P2719H;1;;2022-04-04;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-092;DELL P2719H;43;;2021-07-29;2023-06-16;Monitor;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-093;DELL P2719H;2;;2021-07-29;2023-06-16;Monitor;In stock;France;;;;MY ENTERPRISE;;365;;; -physical-eq-094;DELL P2721Q;2;;2023-02-24;2023-06-16;Monitor;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-095;DELL S2216H;2;;2024-11-27;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-096;DELL S2216H;17;;2021-05-21;2023-06-16;Monitor;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-097;DELL S2216H;1;;2022-11-22;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-098;DELL S2240L;28;;2021-06-26;2023-06-16;Monitor;In use;France;;;;MY ENTERPRISE;;365;;; -physical-eq-099;DELL S2240L;8;;2022-12-04;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; -physical-eq-100;DELL S2240L;4;;2024-12-09;2023-06-16;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;; +nomEquipementPhysique;modele;quantite;nomCourtDatacenter;dateAchat;dateRetrait;dureeUsageInterne;dureeUsageAmont;dureeUsageAval;type;statut;paysDUtilisation;consoElecAnnuelle;utilisateur;nomSourceDonnee;nomEntite;nbCoeur;nbJourUtiliseAn;goTelecharge;modeUtilisation;tauxUtilisation;qualite +physical-eq-001;P2719;1;;2021-03-30;2023-06-16;4.5;1;2;Monitor;In use;France;;;;MY ENTERPRISE;;365;;COPE;;Haute +physical-eq-002;P2719;2;;;;;1;2;Monitor;In use;France;;;;MY ENTERPRISE;;365;;BYOD;;Basse +physical-eq-003;P2719;4;;2021-03-30;2023-06-16;0.0;0.0;2;Monitor;In use;France;;;;MY ENTERPRISE;;365;;COB;;Moyenne +physical-eq-004;HUB USB;10;;2023-04-01;2023-06-16;0.5;0.5;2;Consumable;Consumed;France;;;;MY ENTERPRISE;;365;;BYOD;0.1;erreur +physical-eq-005;P2720DC;2;;2022-11-04;2023-06-16;-4.5;-1;2;Monitor;In stock;France;;;;MY ENTERPRISE;;365;;BYOD;12.1;moyenne +physical-eq-006;PIXEL 6;1;;2022-10-18;2022-12-18;0.1;0.2;0.2;Communication Device;Missing;France;;;;MY ENTERPRISE;;365;;;test;haute +physical-eq-007;UP2516D;1;;2022-07-31;2023-06-16;4.5;;;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;0.9;basse +physical-eq-008;UP2516D;2;;2022-03-10;2023-06-16;4.5;1;2;Wrong / Type;In stock;France;;;;MY ENTERPRISE;;365;;COPE;0.6; +physical-eq-009;Unknown;3;;2021-08-09;2023-06-16;4.5;1;2;IP Router;In use;France;;;;MY ENTERPRISE;;365;;COPE;0; +physical-eq-010;Unknown;3;;2021-08-09;2023-06-16;4.5;1;2;IP Router;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-011;HP 8440p;1;;2021-08-05;2023-06-16;4.5;1;2;Wrong \type;Missing;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-012;HP 8440p;1;;2023-04-27;2023-06-16;4.5;1;2;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-013;HP 8470w;2;;2025-08-23;2023-06-16;4.5;1;2;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-014;OPPO A72;1;;2023-08-07;2023-06-16;4.5;1;2;Communication Device;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-015;CROSSCALL;1;;2022-08-20;2023-06-16;4.5;1;2;Communication Device;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-016;CROSSCALL;11;;2022-05-20;2023-06-16;4.5;1;2;Communication Device;In stock;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-017;CROSSCALL;8;;2022-05-28;2023-06-16;4.5;1;2;Communication Device;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-018;HUAWEI P9;11;;2021-01-28;2023-06-16;4.5;1;2;Communication Device;In stock;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-019;HUAWEI P9;4;;2022-08-18;2023-06-16;4.5;1;2;Communication Device;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-020;HUAWEI P9;1;;2023-06-18;2023-06-16;4.5;1;2;Communication Device;Missing;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-021;HUAWEI P9;32;;2021-01-28;2023-06-16;4.5;1;2;Communication Device;Missing;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-022;HUAWEI P9;9;;2024-08-18;2023-06-16;4.5;1;2;Communication Device;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-023;PRO MP242;50;;2022-06-21;2023-06-16;4.5;1;2;Monitor;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-024;SAC A DOS;534;;2023-02-18;2023-06-16;4.5;1;2;Consumable;Consumed;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-025;SAC A DOS;1;;2023-02-18;2023-06-16;4.5;1;2;Consumable;Missing;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-026;SPIDER X1;2;;2022-10-17;2023-06-16;4.5;1;2;Communication Device;In stock;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-027;DELL 1909W;5;;2022-11-20;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-028;DELL 1909W;1;;2021-12-20;2023-06-16;4.5;1;2;Monitor;Missing;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-029;DELL 1909W;14;;2025-10-17;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-030;DELL 2412M;1;;2022-12-26;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-031;DELL 2717H;19;;2021-04-08;2023-06-16;4.5;1;2;Monitor;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-032;DELL 2717H;1;;2024-11-23;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-033;DELL E7440;5;;2023-03-19;2023-06-16;4.5;1;2;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-034;DELL E7440;31;;2025-10-27;2023-06-16;4.5;1;2;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-035;DELL E7440;11;;2022-04-24;2023-06-16;4.5;1;2;Personal Computer;Missing;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-036;DELL E7450;2;;2022-12-21;2023-06-16;4.5;1;2;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-037;DELL E7450;14;;2025-10-31;2023-06-16;4.5;1;2;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-038;DELL E7450;6;;2022-04-22;2023-06-16;4.5;1;2;Personal Computer;Missing;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-039;DELL E7470;33;;2023-02-11;2023-06-16;4.5;1;2;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-040;DELL E7470;23;;2022-03-16;2023-06-16;4.5;1;2;Personal Computer;Missing;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-041;DELL E7470;9;;2022-03-16;2023-06-16;4.5;1;2;Personal Computer;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-042;DELL E7470;4;;2022-03-16;2023-06-16;4.5;1;2;Personal Computer;In stock;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-043;DELL E7470;325;;2024-09-01;2023-06-16;4.5;1;2;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-044;DELL E7470;2;;2025-03-03;2023-06-16;4.5;1;2;Personal Computer;In stock;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-045;DELL E7480;349;;2022-12-11;2023-06-16;4.5;1;2;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-046;DELL E7480;49;;2021-10-26;2023-06-16;4.5;1;2;Personal Computer;Missing;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-047;DELL E7480;18;;2021-09-25;2023-06-16;4.5;1;2;Personal Computer;In stock;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-048;DELL E7480;141;;2023-11-04;2023-06-16;4.5;1;2;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-049;DELL E7480;70;;2021-09-30;2023-06-16;4.5;1;2;Personal Computer;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-050;DELL E7480;1;;2025-06-03;2023-06-16;4.5;1;2;Personal Computer;Missing;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-051;DELL E7490;248;;2022-03-21;2023-06-16;4.5;1;2;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-052;DELL E7490;52;;2021-06-17;2023-06-16;4.5;1;2;Personal Computer;In stock;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-053;DELL E7490;421;;2021-06-01;2023-06-16;4.5;1;2;Personal Computer;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-054;DELL E7490;51;;2021-06-19;2023-06-16;4.5;1;2;Personal Computer;Missing;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-055;DELL E7490;6;;2024-04-20;2023-06-16;4.5;1;2;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-056;DELL P1911;8;;2022-07-25;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-057;DELL P1911;6;;2025-01-04;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-058;DELL P1913;4;;2022-11-02;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-059;DELL P1913;2;;2024-04-12;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-060;HUAWEI P20;1;;2021-12-24;2023-06-16;4.5;1;2;Communication Device;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-061;LENOVO M73;13;;2024-01-25;2023-06-16;4.5;1;2;Personal Computer;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-062;LENOVO M73;13;;2022-01-25;2023-06-16;4.5;1;2;Personal Computer;In Use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-063;ANTIVOL MAC;1;;2023-01-14;2023-06-16;4.5;1;2;Consumable;Missing;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-064;ANTIVOL MAC;1;;2023-01-14;2023-06-16;4.5;1;2;Consumable;In stock;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-065;ANTIVOL MAC;10;;2023-01-14;2023-06-16;4.5;1;2;Consumable;Consumed;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-066;AOC U2879VF;10;;2022-11-27;2023-06-16;4.5;1;2;Monitor;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-067;DELL P2210T;1;;2022-12-29;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-068;DELL P2217H;286;;2021-03-13;2023-06-16;4.5;1;2;Monitor;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-069;DELL P2217H;1;;2021-03-13;2023-06-16;4.5;1;2;Monitor;Missing;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-070;DELL P2217H;5;;2022-01-14;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-071;DELL P2217H;6;;2021-03-13;2023-06-16;4.5;1;2;Monitor;In stock;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-072;DELL P2217H;3;;2023-10-15;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-073;DELL P2319H;1;;2022-12-19;2023-06-16;4.5;1;2;Monitor;In stock;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-074;DELL P2319H;49;;2022-12-19;2023-06-16;4.5;1;2;Monitor;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-075;DELL P2412H;1;;2022-03-25;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-076;DELL P2412H;1;;2025-06-01;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-077;DELL P2415Q;7;;2022-03-13;2023-06-16;4.5;1;2;Monitor;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-078;DELL P2415Q;1;;2022-03-13;2023-06-16;4.5;1;2;Monitor;In stock;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-079;DELL P2417H;371;;2021-03-18;2023-06-16;4.5;1;2;Monitor;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-080;DELL P2417H;7;;2022-07-16;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-081;DELL P2417H;4;;2024-07-02;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-082;DELL P2417H;5;;2021-03-18;2023-06-16;4.5;1;2;Monitor;In stock;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-083;DELL P2419H;11;;2021-09-01;2023-06-16;4.5;1;2;Monitor;In stock;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-084;DELL P2419H;11;;2022-10-18;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-085;DELL P2419H;847;;2021-09-01;2023-06-16;4.5;1;2;Monitor;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-086;DELL P2419H;1;;2021-09-01;2023-06-16;4.5;1;2;Monitor;Missing;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-087;DELL P2419H;32;;2024-05-15;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-088;DELL P2422H;7;;2023-04-23;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-089;DELL P2422H;2;;2023-09-30;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-090;DELL P2422H;588;;2022-09-25;2023-06-16;4.5;1;2;Monitor;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-091;DELL P2719H;1;;2022-04-04;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-092;DELL P2719H;43;;2021-07-29;2023-06-16;4.5;1;2;Monitor;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-093;DELL P2719H;2;;2021-07-29;2023-06-16;4.5;1;2;Monitor;In stock;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-094;DELL P2721Q;2;;2023-02-24;2023-06-16;4.5;1;2;Monitor;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-095;DELL S2216H;2;;2024-11-27;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-096;DELL S2216H;17;;2021-05-21;2023-06-16;4.5;1;2;Monitor;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-097;DELL S2216H;1;;2022-11-22;2023-06-16;4.5;1;2;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-098;DELL S2240L;28;;2021-06-26;2023-06-16;4.5;1;2;Monitor;In use;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-099;DELL S2240L;8;;2022-12-04;2023-06-16;4.5;;;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; +physical-eq-100;DELL S2240L;4;;2024-12-09;2023-06-16;4.5;;;Monitor;Retired;France;;;;MY ENTERPRISE;;365;;;; diff --git a/e2e/input_template/EquipementPhysique_serveur.csv b/e2e/input_template/EquipementPhysique_serveur.csv index 21333d8a4f0c061d0502056dd0543e8799190eb9..f444c0b5f7f3f568dc9b6d5101db923e8928bb4b 100644 --- a/e2e/input_template/EquipementPhysique_serveur.csv +++ b/e2e/input_template/EquipementPhysique_serveur.csv @@ -1,101 +1,101 @@ -nomEquipementPhysique;modele;quantite;nomCourtDatacenter;dateAchat;dateRetrait;type;statut;paysDUtilisation;consoElecAnnuelle;utilisateur;nomSourceDonnee;nomEntite;nbCoeur;nbJourUtiliseAn;goTelecharge;modeUtilisation;tauxUtilisation -physical-eq-srv-001;blade-server--28;7;default;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-002;DATACENTER;1;F1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;10;; -physical-eq-srv-003;DATACENTER;1;F1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;20;; -physical-eq-srv-004;DATACENTER;1;F1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;30;; -physical-eq-srv-005;DATACENTER;1;F1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;40;; -physical-eq-srv-006;DATACENTER;1;F1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;50;; -physical-eq-srv-007;DATACENTER;1;F1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-008;DATACENTER;1;F1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-009;DATACENTER;1;F1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-010;DATACENTER;2;F1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-011;DATACENTER;1;F1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-012;DATACENTER;1;F1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-013;DATACENTER;1;F1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-014;DATACENTER;1;G1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-015;DATACENTER;1;G1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-016;DATACENTER;1;G1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-017;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-018;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-019;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-020;DATACENTER;8;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-021;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-022;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-023;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-024;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-025;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-026;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-027;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-028;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-029;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-030;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-031;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-032;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-033;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-034;DATACENTER;1;X1;2016-06-17;2023-06-16;Server;In use;;;;;;;365;;; -physical-eq-srv-035;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-036;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-037;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-038;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-039;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-040;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-041;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-042;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-043;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-044;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-045;DATACENTER;26;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-046;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-047;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-048;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-049;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-050;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-051;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-052;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-053;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-054;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-055;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-056;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-057;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-058;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-059;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-060;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-061;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-062;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-063;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-064;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-065;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-066;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-067;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-068;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-069;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-070;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-071;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-072;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-073;DATACENTER;1;Y1;2016-06-17;2023-06-16;Server;In use;Germany;;;;;;365;;; -physical-eq-srv-074;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-075;DATACENTER;122;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-076;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-077;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-078;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-079;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-080;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-081;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-082;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-083;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-084;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-085;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-086;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-087;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-088;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-089;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-090;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-091;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-092;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-093;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-094;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-095;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-096;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-097;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-098;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-099;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; -physical-eq-srv-100;DATACENTER;1;Z2;2016-06-17;2023-06-16;Server;In use;France;;;;;;365;;; +nomEquipementPhysique;modele;quantite;nomCourtDatacenter;dateAchat;dateRetrait;dureeUsageInterne;dureeUsageAmont;dureeUsageAval;type;statut;paysDUtilisation;consoElecAnnuelle;utilisateur;nomSourceDonnee;nomEntite;nbCoeur;nbJourUtiliseAn;goTelecharge;modeUtilisation;tauxUtilisation;qualite +physical-eq-srv-001;blade-server--28;7;default;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;;Haute +physical-eq-srv-002;DATACENTER;1;F1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;10;;;Basse +physical-eq-srv-003;DATACENTER;1;F1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;20;;;Moyenne +physical-eq-srv-004;DATACENTER;1;F1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;30;;;erreur +physical-eq-srv-005;DATACENTER;1;F1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;40;;; +physical-eq-srv-006;DATACENTER;1;F1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;50;;; +physical-eq-srv-007;DATACENTER;1;F1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-008;DATACENTER;1;F1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-009;DATACENTER;1;F1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-010;DATACENTER;2;F1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-011;DATACENTER;1;F1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-012;DATACENTER;1;F1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-013;DATACENTER;1;F1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-014;DATACENTER;1;G1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-015;DATACENTER;1;G1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-016;DATACENTER;1;G1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-017;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-018;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-019;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-020;DATACENTER;8;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-021;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-022;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-023;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-024;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-025;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-026;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-027;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-028;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-029;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-030;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-031;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-032;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-033;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-034;DATACENTER;1;X1;2016-06-17;2023-06-16;5;1;2;Server;In use;;;;;;;365;;;; +physical-eq-srv-035;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-036;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-037;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-038;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-039;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-040;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-041;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-042;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-043;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-044;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-045;DATACENTER;26;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-046;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-047;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-048;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-049;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-050;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-051;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-052;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-053;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-054;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-055;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-056;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-057;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-058;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-059;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-060;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-061;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-062;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-063;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-064;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-065;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-066;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-067;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-068;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-069;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-070;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-071;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-072;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-073;DATACENTER;1;Y1;2016-06-17;2023-06-16;5;1;2;Server;In use;Germany;;;;;;365;;;; +physical-eq-srv-074;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-075;DATACENTER;122;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-076;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-077;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-078;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-079;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-080;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-081;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-082;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-083;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-084;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-085;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-086;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-087;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-088;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-089;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-090;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-091;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-092;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-093;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-094;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-095;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-096;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-097;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-098;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-099;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; +physical-eq-srv-100;DATACENTER;1;Z2;2016-06-17;2023-06-16;5;1;2;Server;In use;France;;;;;;365;;;; diff --git a/e2e/input_template/EquipementVirtuel.csv b/e2e/input_template/EquipementVirtuel.csv index c6754843426419c199945428bddb65f052f3ee2a..f3ca683e9be8a798a2ce02cc844bdd68c1ed992e 100644 --- a/e2e/input_template/EquipementVirtuel.csv +++ b/e2e/input_template/EquipementVirtuel.csv @@ -1,2 +1,2 @@ -nomEquipementVirtuel;nomEquipementPhysique;nomSourceDonneeEquipementPhysique;cleRepartition;vCPU;cluster;consoElecAnnuelle;typeEqv;capaciteStockage;nomEntite;nomSourceDonnee -virtual-eq-;physical-eq-srv-;;;##VCPU##;##TYPE_EQV##;;calcul;;;; +nomEquipementVirtuel;nomEquipementPhysique;nomSourceDonneeEquipementPhysique;cleRepartition;vCPU;cluster;consoElecAnnuelle;typeEqv;capaciteStockage;nomEntite;nomSourceDonnee;qualite +virtual-eq-;physical-eq-srv-;;;##VCPU##;##TYPE_EQV##;;calcul;;;;basse diff --git a/e2e/input_template/OperationNonIT.csv b/e2e/input_template/OperationNonIT.csv new file mode 100644 index 0000000000000000000000000000000000000000..66ad0e21b9b44d0b5d94deb99cfd8b92cc7484ea --- /dev/null +++ b/e2e/input_template/OperationNonIT.csv @@ -0,0 +1,21 @@ +nomItemNonIT;quantite;type;dureeDeVie;localisation;nomEntite;nomSourceDonnee;nomCourtDatacenter;description;consoElecAnnuelle;qualite +reseau-fixe-1;100.0;Fixed Line FR;;France;SSG;sourceTest;;description;;moyenne +reseau-fixe-2;20.0;Fixed Line EU;;Hungary;Entite;sourceTest2;;description;;haUte +reseau-fixe-error;20.0;Fixed Line;;Hungary;Entite;sourceTest2;;description;; +reseau-mobile-1;445.0;Mobile Line;;France;EntiteTest;sourceTest3;;description;;erreur +batiment-dsi-stMalo;1000.0;Batiment 1;45.0;France;EntiteTest;sourceTest4;;description;;HAUTE +batiment-dsi-Rennes;1200.0;Batiment 1;;France;EntiteTest;sourceTest5;;description;;bas +batiment-dsi-Cesson;1060.0;Batiment 2;;France;EntiteTest;sourceTest6;;description;;Basse +batiment-dc-stMalo;836.0;Batiment DC;25.0;France;EntiteTest;sourceTest7;fakeName;description;; +batiment-dc-Cesson;590.0;Batiment DC;;France;EntiteTest;sourceTest8;G1;description;; +maintenance-1;30.0;Wrong/type;;France;EntiteTest;sourceTest9;;description;; +deplacement-velo;1230.0;Deplacement Velo;;France;EntiteTest;sourceTest10;;description;; +deplacement-trotinette;60.0;Deplacement Trotinette;;France;EntiteTest;sourceTest11;;description;; +deplacement-voiture-electrique;156.0;Deplacement Voiture Electrique;;France;EntiteTest;sourceTest12;;description;; +deplacement-voiture-hybride;3457.0;Deplacement Voiture Hybride;;France;EntiteTest;sourceTest13;;description;; +deplacement-voiture-essence;24678.0;Deplacement Voiture Essence;;France;EntiteTest;sourceTest14;;description;; +deplacement-voiture-diesel;2355.0;Deplacement Voiture Diesel;;France;EntiteTest;sourceTest15;;description;; +deplacement-avion;23000.0;Deplacement Avion;;France;EntiteTest;sourceTest16;;description;; +deplacement-train;27000.0;Deplacement Train;;France;EntiteTest;sourceTest17;;description;; +deplacement-bus-essence;352.0;Deplacement Bus Essence;;France;EntiteTest;sourceTest18;;description;; +deplacement-bus-electrique;352.0;Deplacement Bus Electrique;;France;EntiteTest;sourceTest18;;description;; diff --git a/e2e/performance-test.sh b/e2e/performance-test.sh index 31a9b4a426a901a2b1026928d344cb732a3d6528..0259dca4dfe0e47f13ad731be2ea62daa80aab66 100644 --- a/e2e/performance-test.sh +++ b/e2e/performance-test.sh @@ -1,12 +1,13 @@ #!/bin/bash # Call: sh performance-test.sh -# Call: sh performance-test.sh E2E auto auto SYNC -# Call: sh performance-test.sh 1 orgX perf ASYNC +# Call: sh performance-test.sh E2E auto auto SYNC REEL +# Call: sh performance-test.sh 1 orgX perf ASYNC FIXE SCENARIO=${1:-E2E} ORGANISATION=${2:-auto} LOT_PREFIX=${3:-auto} MODE=${4:-SYNC} +DUREE_USAGE=${5:-FIXE} . ./.env @@ -42,7 +43,7 @@ for nbIt in ${!cfg_scenario}; do for ((j = 1; j <= $nbIt; j++)); do ### For each iteration load input, submit calculations and check ### echo "*** Organisation: $ORGANISATION, NomLot: ${LOT_PREFIX}_${dataset}_${j} ***" - sh 3_load_input.sh $ORGANISATION ${LOT_PREFIX}_${dataset}_${j} $SCENARIO $MODE + sh 3_load_input.sh $ORGANISATION ${LOT_PREFIX}_${dataset}_${j} $SCENARIO $MODE $DUREE_USAGE start_it=$(date +%s) sh 4_check.sh $ORGANISATION ${LOT_PREFIX}_${dataset}_${j} end_it=$(date +%s) diff --git a/services/.workspace/.idea/modules.xml b/services/.workspace/.idea/modules.xml index b4f71b368614e1b88ac4fdfbdd5ea72860dd5bb4..bdb487351f4aba3d5223de9577c0844150a2daab 100644 --- a/services/.workspace/.idea/modules.xml +++ b/services/.workspace/.idea/modules.xml @@ -2,7 +2,6 @@ <project version="4"> <component name="ProjectModuleManager"> <modules> - <module fileurl="file://$PROJECT_DIR$/../../e2e/e2e.iml" filepath="$PROJECT_DIR$/../../e2e/e2e.iml" /> </modules> </component> </project> \ No newline at end of file diff --git a/services/.workspace/.idea/saveactions_settings.xml b/services/.workspace/.idea/saveactions_settings.xml index 898dbf8532d66ffc2f4694b0f05eb607626ebe1d..b1eaeeab18d419ba2edb687ca7b8b0943d6b3cee 100644 --- a/services/.workspace/.idea/saveactions_settings.xml +++ b/services/.workspace/.idea/saveactions_settings.xml @@ -11,6 +11,7 @@ <option name="configurationPath" value="" /> <option name="exclusions"> <set> + <option value=".*\.adoc" /> <option value=".*\.yaml" /> <option value=".*\.yml" /> </set> diff --git a/services/api-event-calculs/pom.xml b/services/api-event-calculs/pom.xml index cea2f3bc87a8faf7a0e5b9806e8e8b9484983d16..2e50d428aac36eac909eb925d6bec2d637426607 100644 --- a/services/api-event-calculs/pom.xml +++ b/services/api-event-calculs/pom.xml @@ -5,12 +5,12 @@ <parent> <groupId>org.mte.numecoeval</groupId> <artifactId>core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <artifactId>api-event-calculs</artifactId> <name>api-event-calculs</name> - <version>1.3.0</version> + <version>1.4.0</version> <description>api-event-calculs</description> <repositories> diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/domain/model/CalculOperationNonIT.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/domain/model/CalculOperationNonIT.java new file mode 100644 index 0000000000000000000000000000000000000000..df37017aa0c58067e6b6e07ec7c846372954edbe --- /dev/null +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/domain/model/CalculOperationNonIT.java @@ -0,0 +1,21 @@ +package org.mte.numecoeval.calculs.domain.model; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.mte.numecoeval.calculs.referentiels.generated.api.model.*; +import org.mte.numecoeval.topic.data.OperationNonITDTO; + +import java.util.List; + +@NoArgsConstructor +@Getter +@Setter +public class CalculOperationNonIT { + private List<EtapeDTO> etapes; + private List<CritereDTO> criteres; + private List<HypotheseDTO> hypotheses; + private OperationNonITDTO operationNonIT; + private TypeItemDTO typeItem; + private List<FacteurCaracterisationDTO> facteurCaracterisations; +} \ No newline at end of file diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/domain/model/CalculSizes.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/domain/model/CalculSizes.java index bd90d22d26ce0924e171aee5bad07cbfd30d997a..89f9b8984ef5da314d27f76577b7e9c9d724509e 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/domain/model/CalculSizes.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/domain/model/CalculSizes.java @@ -7,10 +7,12 @@ public class CalculSizes { private long nbEquipementPhysique; private long nbEquipementVirtuel; private long nbApplication; + private long nbOperationNonIT; private long nbMessagerie; private long nbIndicateurEquipementPhysique; private long nbIndicateurEquipementVirtuel; private long nbIndicateurApplication; private long nbIndicateurReseau; + private long nbIndicateurOperationNonIT; private long nbIndicateurMessagerie; } diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/client/ReferentielClient.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/client/ReferentielClient.java index 92f1d225ca88f9bfc4996c7ead8aec7a343267a5..ba9e0e067caab98e089fc87f604ee06f38919ffb 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/client/ReferentielClient.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/client/ReferentielClient.java @@ -3,6 +3,7 @@ package org.mte.numecoeval.calculs.infrastructure.client; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.mte.numecoeval.calculs.domain.exception.ExternalApiException; +import org.mte.numecoeval.calculs.domain.utils.Constants; import org.mte.numecoeval.calculs.referentiels.generated.api.client.InterneNumEcoEvalApi; import org.mte.numecoeval.calculs.referentiels.generated.api.model.*; import org.springframework.cache.annotation.Cacheable; @@ -82,6 +83,18 @@ public class ReferentielClient { return null; } + @Cacheable(value = "TypeItem") + public TypeItemDTO getTypeItem(String type) { + try { + return interneNumEcoEvalApi.getTypeItem(type).block(); + } catch (WebClientResponseException e) { + if (e.getStatusCode() != HttpStatusCode.valueOf(404)) { + throw new ExternalApiException(e); + } + } + return null; + } + @Cacheable(value = "ImpactEquipement") public ImpactEquipementDTO getImpactEquipement(String refEquipement, String critere, String etape) { try { @@ -119,6 +132,30 @@ public class ReferentielClient { return null; } + @Cacheable(value = "FacteurCaracterisationMixElec") + public FacteurCaracterisationDTO getMixElectriqueFromFacteurCaracterisation(String critere, String localisation) { + try { + return interneNumEcoEvalApi.getFacteurCaracterisation(critere, null, null, localisation, Constants.ELECTRICITY_MIX_CATEGORY).blockFirst(); + } catch (WebClientResponseException e) { + if (e.getStatusCode() != HttpStatusCode.valueOf(404)) { + throw new ExternalApiException(e); + } + } + return null; + } + + @Cacheable(value = "FacteurCaracterisation") + public FacteurCaracterisationDTO getFacteurCaracterisationByCritereAndEtapeAndNom(String critere, String etape, String nom) { + try { + return interneNumEcoEvalApi.getFacteurCaracterisation(critere, etape, nom, null, null).blockFirst(); + } catch (WebClientResponseException e) { + if (e.getStatusCode() != HttpStatusCode.valueOf(404)) { + throw new ExternalApiException(e); + } + } + return null; + } + @Cacheable(value = "ImpactMessagerie") public ImpactMessagerieDTO getMessagerie(String critere) { try { diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/config/CacheConfig.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/config/CacheConfig.java index ab24eb9dae3b196dd930f13184bd9d683861350f..5e182885f8c098c5c3518af9908a90cec1b208c9 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/config/CacheConfig.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/config/CacheConfig.java @@ -22,11 +22,16 @@ public class CacheConfig { "Criteres", "Hypothese", "TypeEquipement", + "TypeItem", "CorrespondanceRefEquipement", + "FacteurCaracterisationMixElec", + "FacteurCaracterisation", "ImpactEquipement", "ImpactReseau", "MixElectrique", + "ImpactOperationNonIT", "ImpactMessagerie", + "DureeUsage", }, allEntries = true) @Scheduled(fixedRateString = "${numecoeval.cache.ttl}", timeUnit = TimeUnit.MINUTES) public void emptyAllCaches() { diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/config/DomainConfiguration.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/config/DomainConfiguration.java index 0986a1d432c9c31a0044b6d0794c73a835021b1a..d41eaae9ae9a7359c783b2853d15e3b6d9f88d6e 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/config/DomainConfiguration.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/config/DomainConfiguration.java @@ -15,34 +15,35 @@ public class DomainConfiguration { } @Bean - public CalculImpactEquipementPhysiqueService calculImpactEquipementPhysiqueService(DureeDeVieEquipementPhysiqueService dureeDeVieEquipementPhysiqueService, ObjectMapper objectMapper) { + public CalculImpactEquipementPhysiqueService calculImpactEquipementPhysiqueService(DureeDeVieEquipementPhysiqueService dureeDeVieEquipementPhysiqueService) { return new CalculImpactEquipementPhysiqueServiceImpl( - dureeDeVieEquipementPhysiqueService, - objectMapper - ); + dureeDeVieEquipementPhysiqueService); } @Bean - CalculImpactEquipementVirtuelService calculImpactEquipementVirtuelService(ObjectMapper objectMapper) { - return new CalculImpactEquipementVirtuelServiceImpl(objectMapper); + CalculImpactEquipementVirtuelService calculImpactEquipementVirtuelService() { + return new CalculImpactEquipementVirtuelServiceImpl(); } @Bean - CalculImpactApplicationService calculImpactApplicationService(ObjectMapper objectMapper) { - return new CalculImpactApplicationServiceImpl(objectMapper); + CalculImpactApplicationService calculImpactApplicationService() { + return new CalculImpactApplicationServiceImpl(); } @Bean - public CalculImpactReseauService calculImpactReseauService(ObjectMapper objectMapper) { - return new CalculImpactReseauServiceImpl( - objectMapper - ); + public CalculImpactReseauService calculImpactReseauService() { + return new CalculImpactReseauServiceImpl(); + } + + @Bean + public CalculImpactOperationNonITService calculImpactOperationNonITService() { + return new CalculImpactOperationNonITServiceImpl(); } @Bean CalculImpactMessagerieService calculImpactMessagerieService(ObjectMapper objectMapper) { - return new CalculImpactMessagerieServiceImpl(objectMapper); + return new CalculImpactMessagerieServiceImpl(); } } diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/export/IndicateurController.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/export/IndicateurController.java index f3b51d7325945f1397e17058fbe5199df32975de..e3a93ebb821c20752e70cf4c9e6ae379c94c28f5 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/export/IndicateurController.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/export/IndicateurController.java @@ -16,6 +16,9 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.List; +/** + * Création d'API utilisées uniquement pour les tests e2e + */ @RestController @Slf4j @Profile("!prod & !test") @@ -127,6 +130,31 @@ public class IndicateurController { } } + @GetMapping("/operationNonITCsv") + public String getOperationNonITList( + @RequestParam String nomLot, + @RequestParam String nomOrganisation, + @RequestParam String fields + ) { + + try (Connection conn = dataSource.getConnection()) { + try (var ps = conn.prepareStatement(String.format(""" + SELECT %s + FROM ind_indicateur_impact_operation_non_it + WHERE nom_lot = ? AND nom_organisation = ? + ORDER BY nom_item_non_it, critere, etapeacv; + """, fields))) { + + ps.setString(1, nomLot); + ps.setString(2, nomOrganisation); + return resultSetToCsv(ps.executeQuery()); + } + } catch (SQLException e) { + log.error("SQl exception", e); + throw new RuntimeException(e); + } + } + private String resultSetToCsv(ResultSet rs) throws SQLException { List<String> lines = new ArrayList<>(); @@ -142,14 +170,9 @@ public class IndicateurController { rows++; List<String> values = new ArrayList<>(); for (int i = 1; i <= numCols; i++) { - try { - var value = rs.getDouble(i); - values.add(String.valueOf(value)); - } catch (Exception e) { - var value = rs.getString(i); - if (value == null) value = ""; - values.add(value); - } + var value = rs.getString(i); + if (value == null) value = ""; + values.add(value); } lines.add(String.join(",", values)); if (rows >= MAX_ROWS) break; diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsApplicationController.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsApplicationController.java index f4b664a9246facabff8596ee11db75cca923a299..aaf3b2652ad73f43dd7a53bbd6a3dd425d2db14a 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsApplicationController.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsApplicationController.java @@ -31,9 +31,7 @@ public class CalculsApplicationController implements CalculsApplicationApi { public ResponseEntity<IndicateurImpactApplicationRest> calculerImpactApplication(DemandeCalculApplicationRest demandeCalculApplicationRest) { var demandeCalcul = domainMapper.toDomain(demandeCalculApplicationRest); - var indicateur = new CalculImpactApplicationServiceImpl( - objectMapper - ).calculImpactApplicatif(demandeCalcul); + var indicateur = new CalculImpactApplicationServiceImpl().calculImpactApplicatif(demandeCalcul); return checkIndicateurService.isOk(indicateur.getStatutIndicateur()) ? ResponseEntity.ok(domainMapper.toRest(indicateur)) : diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsEquipementPhysiqueController.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsEquipementPhysiqueController.java index a74e53bba840542455b3c7bc349c8003cd49adfd..83230222193895b1fd129ac3a9b13d9e556879a5 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsEquipementPhysiqueController.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsEquipementPhysiqueController.java @@ -25,7 +25,7 @@ public class CalculsEquipementPhysiqueController implements CalculsEquipementPhy DureeDeVieEquipementPhysiqueService dureeDeVieEquipementPhysiqueService; CheckIndicateurService checkIndicateurService; - + /** * POST /calculs/equipementPhysique * @@ -37,8 +37,7 @@ public class CalculsEquipementPhysiqueController implements CalculsEquipementPhy var demandeCalcul = domainMapper.toDomain(demandeCalculImpactEquipementPhysiqueRest); var indicateur = new CalculImpactEquipementPhysiqueServiceImpl( - dureeDeVieEquipementPhysiqueService, - objectMapper + dureeDeVieEquipementPhysiqueService ).calculerImpactEquipementPhysique(demandeCalcul); return checkIndicateurService.isOk(indicateur.getStatutIndicateur()) ? diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsEquipementVirtuelController.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsEquipementVirtuelController.java index 66ee73ecc2cfa991cd242b33b5ae2914be564567..089c1a897de3450164f25674c6908bde6f863387 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsEquipementVirtuelController.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsEquipementVirtuelController.java @@ -20,7 +20,7 @@ public class CalculsEquipementVirtuelController implements CalculsEquipementVirt ObjectMapper objectMapper; CheckIndicateurService checkIndicateurService; - + /** * POST /calculs/equipementVirtuel * @@ -31,9 +31,7 @@ public class CalculsEquipementVirtuelController implements CalculsEquipementVirt public ResponseEntity<IndicateurImpactEquipementVirtuelRest> calculerImpactEquipementVirtuel(DemandeCalculEquipementVirtuelRest demandeCalculEquipementVirtuelRest) { var demandeCalcul = domainMapper.toDomain(demandeCalculEquipementVirtuelRest); - var indicateur = new CalculImpactEquipementVirtuelServiceImpl( - objectMapper - ).calculerImpactEquipementVirtuel(demandeCalcul); + var indicateur = new CalculImpactEquipementVirtuelServiceImpl().calculerImpactEquipementVirtuel(demandeCalcul); return checkIndicateurService.isOk(indicateur.getStatutIndicateur()) ? ResponseEntity.ok(domainMapper.toRest(indicateur)) : diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsMessagerieController.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsMessagerieController.java index 79ad2e4b542d225c16ee84ab94ea42efec0949a0..dfcf986486d41cf1a38f9aeefa04ff710fa9ba4f 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsMessagerieController.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsMessagerieController.java @@ -31,9 +31,7 @@ public class CalculsMessagerieController implements CalculsMessagerieApi { public ResponseEntity<IndicateurImpactMessagerieRest> calculerImpactMessagerie(DemandeCalculMessagerieRest demandeCalculMessagerieRest) { var demandeCalcul = domainMapper.toDomain(demandeCalculMessagerieRest); - var indicateur = new CalculImpactMessagerieServiceImpl( - objectMapper - ).calculerImpactMessagerie(demandeCalcul); + var indicateur = new CalculImpactMessagerieServiceImpl().calculerImpactMessagerie(demandeCalcul); return checkIndicateurService.isOk(indicateur.getStatutIndicateur()) ? ResponseEntity.ok(domainMapper.toRest(indicateur)) : diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsOperationNonITController.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsOperationNonITController.java new file mode 100644 index 0000000000000000000000000000000000000000..df0e0561e3fbdf06716a7625b14df9cc09c83645 --- /dev/null +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsOperationNonITController.java @@ -0,0 +1,39 @@ +package org.mte.numecoeval.calculs.infrastructure.controller.rest.calculs; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.mte.numecoeval.calculs.domain.port.input.service.impl.CalculImpactOperationNonITServiceImpl; +import org.mte.numecoeval.calculs.infrastructure.mapper.DomainMapper; +import org.mte.numecoeval.calculs.infrastructure.service.rest.calculs.CheckIndicateurService; +import org.mte.numecoeval.calculs.rest.generated.api.model.DemandeCalculImpactOperationNonITRest; +import org.mte.numecoeval.calculs.rest.generated.api.model.IndicateurImpactOperationNonITRest; +import org.mte.numecoeval.calculs.rest.generated.api.server.CalculsOperationNonItApi; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Slf4j +@AllArgsConstructor +public class CalculsOperationNonITController implements CalculsOperationNonItApi { + + DomainMapper domainMapper; + + CheckIndicateurService checkIndicateurService; + + /** + * POST /calculs/operationNonIT + * + * @param demandeCalculImpactOperationNonITRest (required) + * @return la liste d'indicateurs calcules + */ + @Override + public ResponseEntity<IndicateurImpactOperationNonITRest> calculerImpactOperationNonIT(DemandeCalculImpactOperationNonITRest demandeCalculImpactOperationNonITRest) { + var demandeCalcul = domainMapper.toDomain(demandeCalculImpactOperationNonITRest); + + var indicateur = new CalculImpactOperationNonITServiceImpl().calculerImpactOperationNonIT(demandeCalcul); + + return checkIndicateurService.isOk(indicateur.getStatutIndicateur()) ? + ResponseEntity.ok(domainMapper.toRest(indicateur)) : + ResponseEntity.badRequest().body(domainMapper.toRest(indicateur)); + } +} diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsReseauController.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsReseauController.java index 0e7f8f8912cb2b3736076b48c4279ea85620bd03..f859f33038835b82a3cd1f3af166e2af340eddf0 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsReseauController.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/rest/calculs/CalculsReseauController.java @@ -20,7 +20,7 @@ public class CalculsReseauController implements CalculsReseauApi { ObjectMapper objectMapper; CheckIndicateurService checkIndicateurService; - + /** * POST /calculs/reseau/equipementPhysique * @@ -31,9 +31,7 @@ public class CalculsReseauController implements CalculsReseauApi { public ResponseEntity<IndicateurImpactReseauRest> calculerImpactReseau(DemandeCalculImpactReseauEquipementPhysiqueRest demandeCalculImpactReseauEquipementPhysiqueRest) { var demandeCalcul = domainMapper.toDomain(demandeCalculImpactReseauEquipementPhysiqueRest); - var indicateur = new CalculImpactReseauServiceImpl( - objectMapper - ).calculerImpactReseau(demandeCalcul); + var indicateur = new CalculImpactReseauServiceImpl().calculerImpactReseau(demandeCalcul); return checkIndicateurService.isOk(indicateur.getStatutIndicateur()) ? ResponseEntity.ok(domainMapper.toRest(indicateur)) : diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/sync/calculs/SyncCalculsController.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/sync/calculs/SyncCalculsController.java index 4b1df0092404ef452c172c5602d5ec849c33c5d9..327e85e39a178f701f61365807f64f39066a77ff 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/sync/calculs/SyncCalculsController.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/controller/sync/calculs/SyncCalculsController.java @@ -4,13 +4,13 @@ import lombok.AllArgsConstructor; import org.mte.numecoeval.calculs.infrastructure.service.sync.calculs.SyncCalculService; import org.mte.numecoeval.calculs.sync.generated.api.model.ReponseCalculRest; import org.mte.numecoeval.calculs.sync.generated.api.model.SyncCalculRest; -import org.mte.numecoeval.calculs.sync.generated.api.server.CalculsEquipementPhysiqueEtMessagerieApi; +import org.mte.numecoeval.calculs.sync.generated.api.server.CalculsEquipementPhysiqueEtOperationNonItEtMessagerieApi; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; @RestController @AllArgsConstructor -public class SyncCalculsController implements CalculsEquipementPhysiqueEtMessagerieApi { +public class SyncCalculsController implements CalculsEquipementPhysiqueEtOperationNonItEtMessagerieApi { SyncCalculService syncCalculService; diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/kafkalistener/ListenOperationNonIT.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/kafkalistener/ListenOperationNonIT.java new file mode 100644 index 0000000000000000000000000000000000000000..61b4e1c079b589448125f98653e40ab651990e3e --- /dev/null +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/kafkalistener/ListenOperationNonIT.java @@ -0,0 +1,21 @@ +package org.mte.numecoeval.calculs.infrastructure.kafkalistener; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.mte.numecoeval.calculs.infrastructure.service.calcul.MainOperationNonITService; +import org.mte.numecoeval.topic.data.OperationNonITDTO; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.stereotype.Component; + +@Component +@Slf4j +@AllArgsConstructor +public class ListenOperationNonIT { + + private MainOperationNonITService mainOperationNonITService; + + @KafkaListener(topics = "${numecoeval.topic.operationNonIT}", concurrency = "${numecoeval.topic.partition}") + public void consume(OperationNonITDTO OperationNonITDTO) { + mainOperationNonITService.calcul(OperationNonITDTO); + } +} \ No newline at end of file diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/mapper/DomainMapper.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/mapper/DomainMapper.java index a5c6c049c9ec4b54b8de7e4e5b7475ec65e687dd..47ef6c1b8ad71bac48517f30bbf97ce2815951a8 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/mapper/DomainMapper.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/mapper/DomainMapper.java @@ -22,7 +22,9 @@ public interface DomainMapper { Messagerie toDomain(MessagerieRest rest); - /*Référentiels*/ + OperationNonIT toDomain(OperationNonITRest rest); + + /* Référentiels */ ReferentielTypeEquipement toDomain(TypeEquipementRest rest); @@ -58,6 +60,8 @@ public interface DomainMapper { IndicateurImpactReseauRest toRest(ImpactReseau domain); + IndicateurImpactOperationNonITRest toRest(ImpactOperationNonIT domain); + IndicateurImpactMessagerieRest toRest(ImpactMessagerie domain); /*Demandes*/ @@ -66,13 +70,16 @@ public interface DomainMapper { @Mapping(target = "dateCalcul", expression = "java(java.time.LocalDateTime.now())") DemandeCalculImpactReseau toDomain(DemandeCalculImpactReseauEquipementPhysiqueRest rest); - + @Mapping(target = "dateCalcul", expression = "java(java.time.LocalDateTime.now())") DemandeCalculImpactEquipementVirtuel toDomain(DemandeCalculEquipementVirtuelRest rest); @Mapping(target = "dateCalcul", expression = "java(java.time.LocalDateTime.now())") DemandeCalculImpactApplication toDomain(DemandeCalculApplicationRest rest); + @Mapping(target = "dateCalcul", expression = "java(java.time.LocalDateTime.now())") + DemandeCalculImpactOperationNonIT toDomain(DemandeCalculImpactOperationNonITRest rest); + @Mapping(target = "dateCalcul", expression = "java(java.time.LocalDateTime.now())") DemandeCalculImpactMessagerie toDomain(DemandeCalculMessagerieRest rest); } diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/mapper/EntreesMapper.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/mapper/EntreesMapper.java index be2c6c0b8abde8a9f04c54f6d5109218c17f355c..7041fe496b8c6332aaf000a02c8702c45478ebac 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/mapper/EntreesMapper.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/mapper/EntreesMapper.java @@ -4,9 +4,11 @@ import org.mapstruct.Mapper; import org.mte.numecoeval.calculs.domain.data.entree.DataCenter; import org.mte.numecoeval.calculs.domain.data.entree.EquipementPhysique; import org.mte.numecoeval.calculs.domain.data.entree.Messagerie; +import org.mte.numecoeval.calculs.domain.data.entree.OperationNonIT; import org.mte.numecoeval.topic.data.DataCenterDTO; import org.mte.numecoeval.topic.data.EquipementPhysiqueDTO; import org.mte.numecoeval.topic.data.MessagerieDTO; +import org.mte.numecoeval.topic.data.OperationNonITDTO; @Mapper(componentModel = "spring") public interface EntreesMapper { @@ -15,6 +17,8 @@ public interface EntreesMapper { DataCenter toDomain(DataCenterDTO dto); + OperationNonIT toDomain(OperationNonITDTO dto); + Messagerie toDomain(MessagerieDTO messagerieDTO); } diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/mapper/ReferentielMapper.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/mapper/ReferentielMapper.java index b6937550fd7a1828959e8792c1c29fe90ff8ba3d..6624cc54ba6c58c9e158af0f77cba530a80f1e06 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/mapper/ReferentielMapper.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/mapper/ReferentielMapper.java @@ -23,6 +23,10 @@ public interface ReferentielMapper { List<ReferentielHypothese> toListHypothese(List<HypotheseDTO> hypotheseDTO); + ReferentielFacteurCaracterisation toFacteurCaracterisation(FacteurCaracterisationDTO facteurCaracterisationDTO); + + List<ReferentielFacteurCaracterisation> toListFacteurCaracterisation(List<FacteurCaracterisationDTO> facteurCaracterisationDTO); + ReferentielImpactEquipement toImpactEquipement(ImpactEquipementDTO impactEquipementDTO); List<ReferentielImpactEquipement> toListImpactEquipement(List<ImpactEquipementDTO> impactEquipementDTO); @@ -38,4 +42,6 @@ public interface ReferentielMapper { ReferentielCorrespondanceRefEquipement toCorrespondanceRefEquipement(CorrespondanceRefEquipementDTO dto); ReferentielTypeEquipement toTypeEquipement(TypeEquipementDTO dto); + + ReferentielTypeItem toTypeItem(TypeItemDTO dto); } diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/ApplicationRepository.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/ApplicationRepository.java index 574d05764f732caf79ca66be68ded28b90c637d2..4e5220f547888b07e8efa3b399dcafa793b08d7e 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/ApplicationRepository.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/ApplicationRepository.java @@ -53,6 +53,7 @@ public class ApplicationRepository { .domaine(rs.getString("domaine")) .sousDomaine(rs.getString("sous_domaine")) .nomSourceDonnee(rs.getString("nom_source_donnee")) + .qualite(rs.getString("qualite")) .build()); } } diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/DonneesEntreeRepository.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/DonneesEntreeRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..d23d6cdd462b80a38913537cc472d92cc74a64ca --- /dev/null +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/DonneesEntreeRepository.java @@ -0,0 +1,48 @@ +package org.mte.numecoeval.calculs.infrastructure.repository; + +import lombok.extern.slf4j.Slf4j; +import org.mte.numecoeval.calculs.domain.exception.DatabaseException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +@Component +@Slf4j +public class DonneesEntreeRepository { + + @Autowired + private DataSource dataSource; + + @Cacheable("DureeUsage") + public String findDureeUsage(String nomLot, String nomOrganisation) { + List<String> result = new ArrayList<>(); + try (Connection conn = dataSource.getConnection()) { + try (var ps = conn.prepareStatement(""" + SELECT duree_usage + FROM en_donnees_entrees + WHERE nom_lot = ? AND nom_organisation= ? + """)) { + + ps.setString(1, nomLot); + ps.setString(2, nomOrganisation); + var rs = ps.executeQuery(); + while (rs.next()) { + result.add(rs.getString("duree_usage")); + } + } + } catch (SQLException e) { + log.error("Une erreur s'est produite lors de la selection dans PostgreSQL. Exception: ", e); + throw new DatabaseException(e); + } + if (result.isEmpty()) { + return null; + } + return result.getFirst(); + } +} diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/EquipementPhysiqueRepository.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/EquipementPhysiqueRepository.java index 11864627976fb6634c256a55dbb189a254781329..af9a3e6ea70e99703142601ad741b108d8aa2baa 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/EquipementPhysiqueRepository.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/EquipementPhysiqueRepository.java @@ -35,7 +35,8 @@ public class EquipementPhysiqueRepository { dc.localisation as dc_localisation, dc.nom_long_datacenter as dc_nom_long_datacenter, dc.pue as dc_pue, - dc.nom_entite as dc_nom_entite + dc.nom_entite as dc_nom_entite, + dc.qualite as dc_qualite FROM en_equipement_physique eqp LEFT JOIN en_data_center dc ON dc.nom_lot = eqp.nom_lot and dc.nom_court_datacenter = eqp.nom_court_datacenter WHERE eqp.id = ANY (?) @@ -55,6 +56,9 @@ public class EquipementPhysiqueRepository { .consoElecAnnuelle(ResultSetUtils.getDouble(rs, "conso_elec_annuelle")) .dateAchat(ResultSetUtils.getLocalDate(rs, "date_achat")) .dateRetrait(ResultSetUtils.getLocalDate(rs, "date_retrait")) + .dureeUsageInterne(ResultSetUtils.getDouble(rs, "duree_usage_interne")) + .dureeUsageAmont(ResultSetUtils.getDouble(rs, "duree_usage_amont")) + .dureeUsageAval(ResultSetUtils.getDouble(rs, "duree_usage_aval")) .goTelecharge(ResultSetUtils.getFloat(rs, "go_telecharge")) .modele(rs.getString("modele")) .nbCoeur(rs.getString("nb_coeur")) @@ -69,6 +73,7 @@ public class EquipementPhysiqueRepository { .nomSourceDonnee(rs.getString("nom_source_donnee")) .modeUtilisation(rs.getString("mode_utilisation")) .tauxUtilisation(ResultSetUtils.getDouble(rs, "taux_utilisation")) + .qualite(rs.getString("qualite")) .dataCenter( DataCenterDTO.builder() .id(rs.getLong("dc_id")) @@ -79,6 +84,7 @@ public class EquipementPhysiqueRepository { .nomEntite(rs.getString("dc_nom_entite")) .nomOrganisation(rs.getString("nom_organisation")) .dateLot(ResultSetUtils.getLocalDate(rs, "date_lot")) + .qualite(rs.getString("dc_qualite")) .build() ) .build()); diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/EquipementVirtuelRepository.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/EquipementVirtuelRepository.java index 574c2c8c595bca2261f9b89e9eca28cdd4251bfd..14c8c91d4af68f789da90f68f5d7a446a479a73d 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/EquipementVirtuelRepository.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/EquipementVirtuelRepository.java @@ -54,6 +54,7 @@ public class EquipementVirtuelRepository { .capaciteStockage(ResultSetUtils.getDouble(rs, "capacite_stockage")) .cleRepartition(ResultSetUtils.getDouble(rs, "cle_repartition")) .nomSourceDonnee(rs.getString("nom_source_donnee")) + .qualite(rs.getString("qualite")) .build()); } } diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/IndicateurRepository.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/IndicateurRepository.java index 388d866fb95fbd6ececfd17160af9fd1a51f0faf..a2148ebc7194456c2f3ae69e64ef70c93a3e9d21 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/IndicateurRepository.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/IndicateurRepository.java @@ -30,8 +30,8 @@ public class IndicateurRepository { critere, nom_equipement, nom_entite, nom_entite_discriminator, source, statut_indicateur, trace, version_calcul, conso_elec_moyenne, impact_unitaire, quantite, type_equipement, unite, - statut_equipement_physique, nom_lot, nom_source_donnee, nom_source_donnee_discriminator) - VALUES (?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?,?, ?, ?, ?,?, ?, ?, ?,?, ?, ?, ?) + statut_equipement_physique, nom_lot, nom_source_donnee, nom_source_donnee_discriminator, qualite) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?, ?) """; private static final String INSERT_EQUIPEMENT_VIRTUEL_QUERY = """ @@ -39,8 +39,8 @@ public class IndicateurRepository { (date_calcul, date_lot, date_lot_discriminator, nom_organisation, nom_organisation_discriminator, etapeacv, critere, nom_equipement, nom_equipement_virtuel, nom_entite, nom_entite_discriminator, source, statut_indicateur, trace, version_calcul, impact_unitaire, unite, conso_elec_moyenne, - cluster, nom_lot, nom_source_donnee, nom_source_donnee_discriminator ) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + cluster, nom_lot, nom_source_donnee, nom_source_donnee_discriminator, qualite ) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?) """; private static final String INSERT_APPLICATION_QUERY = """ @@ -49,17 +49,26 @@ public class IndicateurRepository { nom_organisation_discriminator, nom_application, type_environnement, nom_equipement_physique, nom_equipement_virtuel, nom_entite, nom_entite_discriminator, source, statut_indicateur, trace, version_calcul, domaine, sous_domaine, impact_unitaire, unite, conso_elec_moyenne, nom_lot, - nom_source_donnee, nom_source_donnee_discriminator) - VALUES (?, ?, ?, ?,?, ?, ?, ?,?, ?, ?, ?,?, ?, ?, ?,?, ?, ?, ?,?,?, ?, ?, ?) + nom_source_donnee, nom_source_donnee_discriminator, qualite) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?) """; + private static final String INSERT_OPERATION_NON_IT_QUERY = """ + INSERT INTO ind_indicateur_impact_operation_non_it + (date_calcul, date_lot, date_lot_discriminator, nom_organisation, nom_organisation_discriminator, etapeacv, + critere, nom_item_non_it, nom_entite, nom_entite_discriminator, source, + statut_indicateur, trace, version_calcul, conso_elec_moyenne, + impact_unitaire, quantite, type_item, unite, + nom_lot, nom_source_donnee, nom_source_donnee_discriminator,qualite) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ,? ,?,?) + """; private static final String INSERT_MESSAGERIE_QUERY = """ INSERT INTO ind_indicateur_impact_messagerie (date_calcul, date_lot, date_lot_discriminator, nom_organisation, nom_organisation_discriminator, critere, mois_annee, nom_entite, nom_entite_discriminator, source, statut_indicateur, trace, version_calcul, impact_mensuel, unite, nombre_mail_emis, volume_total_mail_emis, nom_lot, nom_source_donnee, nom_source_donnee_discriminator) - VALUES (?, ?, ?, ?,?, ?, ?, ?,?, ?, ?, ?,?, ?, ?, ?,?, ?, ?, ?) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) """; private static final String INSERT_RESEAU_QUERY = """ @@ -113,6 +122,7 @@ public class IndicateurRepository { ps.setString(21, indicateur.getNomLot()); ps.setString(22, indicateur.getNomSourceDonnee()); ps.setString(23, StringUtils.defaultString(indicateur.getNomSourceDonnee())); + ps.setString(24, indicateur.getQualite()); ps.addBatch(); } @@ -142,6 +152,7 @@ public class IndicateurRepository { ps.setString(20, indicateur.getNomLot()); ps.setString(21, indicateur.getNomSourceDonnee()); ps.setString(22, StringUtils.defaultString(indicateur.getNomSourceDonnee())); + ps.setString(23, indicateur.getQualite()); ps.addBatch(); } @@ -175,6 +186,7 @@ public class IndicateurRepository { ps.setString(23, indicateur.getNomLot()); ps.setString(24, indicateur.getNomSourceDonnee()); ps.setString(25, StringUtils.defaultString(indicateur.getNomSourceDonnee())); + ps.setString(26, indicateur.getQualite()); ps.addBatch(); } @@ -216,6 +228,56 @@ public class IndicateurRepository { } } + /** + * Sauvegarde tous les indicateurs 'OperationNonIT' en base de données + * + * @param impactOperationNonITs liste indicateurs des Opérations non IT + */ + public void saveIndicateursOperationNonIT(List<ImpactOperationNonIT> impactOperationNonITs) { + if (impactOperationNonITs.isEmpty()) return; + + try (Connection conn = dataSource.getConnection()) { + conn.setAutoCommit(false); + + try (var ps = conn.prepareStatement(INSERT_OPERATION_NON_IT_QUERY)) { + + for (ImpactOperationNonIT indicateur : impactOperationNonITs) { + ps.setTimestamp(1, PreparedStatementUtils.getTimestampFromLocalDateTime(indicateur.getDateCalcul())); + ps.setDate(2, PreparedStatementUtils.getDateFromLocalDate(indicateur.getDateLot())); + ps.setDate(3, PreparedStatementUtils.getDateFromLocalDate(Optional.ofNullable(indicateur.getDateLot()).orElse(LocalDate.EPOCH))); + ps.setString(4, indicateur.getNomOrganisation()); + ps.setString(5, StringUtils.defaultString(indicateur.getNomOrganisation())); + ps.setString(6, indicateur.getEtapeACV()); + ps.setString(7, indicateur.getCritere()); + ps.setString(8, indicateur.getNomItemNonIT()); + ps.setString(9, indicateur.getNomEntite()); + ps.setString(10, StringUtils.defaultString(indicateur.getNomEntite())); + ps.setString(11, indicateur.getSource()); + ps.setString(12, indicateur.getStatutIndicateur()); + ps.setString(13, indicateur.getTrace()); + ps.setString(14, indicateur.getVersionCalcul()); + PreparedStatementUtils.setDoubleValue(ps, 15, indicateur.getConsoElecMoyenne()); + PreparedStatementUtils.setDoubleValue(ps, 16, indicateur.getImpactUnitaire()); + PreparedStatementUtils.setIntValue(ps, 17, indicateur.getQuantite().intValue()); + ps.setString(18, indicateur.getTypeItem()); + ps.setString(19, indicateur.getUnite()); + ps.setString(20, indicateur.getNomLot()); + ps.setString(21, indicateur.getNomSourceDonnee()); + ps.setString(22, StringUtils.defaultString(indicateur.getNomSourceDonnee())); + ps.setString(23, indicateur.getQualite()); + ps.addBatch(); + } + + ps.executeBatch(); + } + + conn.commit(); + } catch (SQLException e) { + log.error("Une erreur s'est produite lors de l'insertion dans PostgreSQL. Exception: ", e); + throw new DatabaseException(e); + } + } + /** * Sauvegarde tous les indicateurs 'messagerie' en base de données * @@ -278,7 +340,7 @@ public class IndicateurRepository { * @param nomEquipementPhysique le nom de l'equipement physique * @param nomLot le nomLot */ - public void clearIndicateurs(String nomEquipementPhysique, String nomLot) { + public void clearIndicateursEquipement(String nomEquipementPhysique, String nomLot) { try (Connection conn = dataSource.getConnection()) { conn.setAutoCommit(false); @@ -324,4 +386,24 @@ public class IndicateurRepository { throw new DatabaseException(e); } } + + public void clearIndicateursOperation(String nomOperationNonIT, String nomLot) { + + try (Connection conn = dataSource.getConnection()) { + conn.setAutoCommit(false); + + try (var ps = conn.prepareStatement(""" + DELETE FROM ind_indicateur_impact_operation_non_it + WHERE nom_lot = ? AND nom_item_non_it = ? + """)) { + ps.setString(1, nomLot); + ps.setString(2, nomOperationNonIT); + ps.execute(); + } + conn.commit(); + } catch (SQLException e) { + log.error("Une erreur s'est produite lors de l'insertion dans PostgreSQL. Exception: ", e); + throw new DatabaseException(e); + } + } } diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/OperationNonITRepository.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/OperationNonITRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..dfda5caf864dc87742b1d2fed280c7138a9445c5 --- /dev/null +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/repository/OperationNonITRepository.java @@ -0,0 +1,81 @@ +package org.mte.numecoeval.calculs.infrastructure.repository; + +import lombok.extern.slf4j.Slf4j; +import org.mte.numecoeval.calculs.domain.exception.DatabaseException; +import org.mte.numecoeval.common.utils.ResultSetUtils; +import org.mte.numecoeval.topic.data.OperationNonITDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +@Component +@Slf4j +public class OperationNonITRepository { + + @Autowired + private DataSource dataSource; + + private static final String COLUMN_NAME_NOM_COURT_DATACENTER = "nom_court_datacenter"; + + public List<OperationNonITDTO> findOperationNonITDTOs(List<Long> ids) { + List<OperationNonITDTO> result = new ArrayList<>(); + + try (Connection conn = dataSource.getConnection()) { + try (var ps = conn.prepareStatement(""" + SELECT * + FROM en_operation_non_it opnit + WHERE id = ANY (?) + """)) { + + ps.setArray(1, conn.createArrayOf("long", ids.toArray(new Long[0]))); + + var rs = ps.executeQuery(); + while (rs.next()) { + result.add(OperationNonITDTO.builder() + .id(rs.getLong("id")) + .nomLot(rs.getString("nom_lot")) + .dateLot(ResultSetUtils.getLocalDate(rs, "date_lot")) + .nomOrganisation(rs.getString("nom_organisation")) + .nomItemNonIT(rs.getString("nom_item_non_it")) + .quantite(ResultSetUtils.getDouble(rs, "quantite")) + .type(rs.getString("type")) + .dureeDeVie(ResultSetUtils.getDouble(rs, "duree_de_vie")) + .localisation(rs.getString("localisation")) + .nomEntite(rs.getString("nom_entite")) + .nomSourceDonnee(rs.getString("nom_source_donnee")) + .nomCourtDatacenter(rs.getString(COLUMN_NAME_NOM_COURT_DATACENTER)) + .description(rs.getString("description")) + .consoElecAnnuelle(ResultSetUtils.getDouble(rs, "conso_elec_annuelle")) + .qualite(rs.getString("qualite")) + .build()); + } + } + } catch (SQLException e) { + log.error("Une erreur s'est produite lors de la selection dans PostgreSQL. Exception: ", e); + throw new DatabaseException(e); + } + + return result; + } + + public void setStatutToTraite(Long id) { + try (Connection conn = dataSource.getConnection()) { + try (var ps = conn.prepareStatement(""" + UPDATE en_operation_non_it + SET statut_traitement = 'TRAITE', date_update = now() + WHERE id = ? + """)) { + ps.setLong(1, id); + ps.execute(); + } + } catch (SQLException e) { + log.error("Une erreur s'est produite lors de la selection dans PostgreSQL. Exception: ", e); + throw new DatabaseException(e); + } + } +} diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/CalculEquipementPhysiqueService.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/CalculEquipementPhysiqueService.java index ee3e0b4b7ca536e8de721301eead3d703323a7a1..c1102a25bd9ea128a501996ab3316cf561e5908c 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/CalculEquipementPhysiqueService.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/CalculEquipementPhysiqueService.java @@ -2,11 +2,13 @@ package org.mte.numecoeval.calculs.infrastructure.service.calcul; import lombok.AllArgsConstructor; import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactEquipementPhysique; +import org.mte.numecoeval.calculs.domain.data.demande.OptionsCalcul; import org.mte.numecoeval.calculs.domain.data.indicateurs.ImpactEquipementPhysique; import org.mte.numecoeval.calculs.domain.model.CalculEquipementPhysique; import org.mte.numecoeval.calculs.domain.port.input.service.CalculImpactEquipementPhysiqueService; import org.mte.numecoeval.calculs.infrastructure.mapper.EntreesMapper; import org.mte.numecoeval.calculs.infrastructure.mapper.ReferentielMapper; +import org.mte.numecoeval.calculs.infrastructure.repository.DonneesEntreeRepository; import org.mte.numecoeval.calculs.referentiels.generated.api.model.CritereDTO; import org.mte.numecoeval.calculs.referentiels.generated.api.model.EtapeDTO; import org.springframework.stereotype.Service; @@ -25,6 +27,8 @@ public class CalculEquipementPhysiqueService { CalculImpactEquipementPhysiqueService calculImpactEquipementPhysiqueService; + DonneesEntreeRepository donneesEntreeRepository; + /** * Calcule les impacts d'un equipement physique * Returne la liste d'impacts en iterant par (etape, critere) @@ -37,6 +41,7 @@ public class CalculEquipementPhysiqueService { LocalDateTime dateCalcul = LocalDateTime.now(); List<ImpactEquipementPhysique> impactEquipementPhysiqueList = new ArrayList<>(); + String dureeUsage = donneesEntreeRepository.findDureeUsage(calculEquipementPhysique.getEquipementPhysique().getNomLot(), calculEquipementPhysique.getEquipementPhysique().getNomOrganisation()); for (EtapeDTO etapeDTO : calculEquipementPhysique.getEtapes()) { for (CritereDTO critereDTO : calculEquipementPhysique.getCriteres()) { @@ -51,6 +56,7 @@ public class CalculEquipementPhysiqueService { .hypotheses(referentielMapper.toListHypothese(calculEquipementPhysique.getHypotheses())) .mixElectriques(referentielMapper.toListMixElectrique(calculEquipementPhysique.getMixElectriques())) .impactEquipements(referentielMapper.toListImpactEquipement(calculEquipementPhysique.getImpactsEquipement())) + .optionsCalcul(new OptionsCalcul(dureeUsage)) .build(); impactEquipementPhysiqueList.add( diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/CalculOperationNonITService.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/CalculOperationNonITService.java new file mode 100644 index 0000000000000000000000000000000000000000..a99aa3fde5f8be27613ab718021c875baffaa297 --- /dev/null +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/CalculOperationNonITService.java @@ -0,0 +1,62 @@ +package org.mte.numecoeval.calculs.infrastructure.service.calcul; + +import lombok.AllArgsConstructor; +import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactOperationNonIT; +import org.mte.numecoeval.calculs.domain.data.indicateurs.ImpactOperationNonIT; +import org.mte.numecoeval.calculs.domain.model.CalculOperationNonIT; +import org.mte.numecoeval.calculs.domain.port.input.service.CalculImpactOperationNonITService; +import org.mte.numecoeval.calculs.infrastructure.mapper.EntreesMapper; +import org.mte.numecoeval.calculs.infrastructure.mapper.ReferentielMapper; +import org.mte.numecoeval.calculs.referentiels.generated.api.model.CritereDTO; +import org.mte.numecoeval.calculs.referentiels.generated.api.model.EtapeDTO; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +@Service +@AllArgsConstructor +public class CalculOperationNonITService { + + EntreesMapper entreesMapper; + + ReferentielMapper referentielMapper; + + CalculImpactOperationNonITService calculImpactOperationNonITService; + + /** + * Calcule les impacts d'une opération non IT + * Returne la liste d'impacts en iterant par (etape, critere) + * + * @param calculOperationNonIT l'opération non IT enrichi + * @return la liste d'impacts + */ + public List<ImpactOperationNonIT> calculImpactOperationNonIT(CalculOperationNonIT calculOperationNonIT) { + + LocalDateTime dateCalcul = LocalDateTime.now(); + + List<ImpactOperationNonIT> impactOperationNonITList = new ArrayList<>(); + + for (EtapeDTO etapeDTO : calculOperationNonIT.getEtapes()) { + for (CritereDTO critereDTO : calculOperationNonIT.getCriteres()) { + + DemandeCalculImpactOperationNonIT demandeCalculImpactOperationNonIT = DemandeCalculImpactOperationNonIT.builder() + .dateCalcul(dateCalcul) + .operationNonIT(entreesMapper.toDomain(calculOperationNonIT.getOperationNonIT())) + .etape(referentielMapper.toEtape(etapeDTO)) + .critere(referentielMapper.toCritere(critereDTO)) + .typeItem(referentielMapper.toTypeItem(calculOperationNonIT.getTypeItem())) + .hypotheses(referentielMapper.toListHypothese(calculOperationNonIT.getHypotheses())) + .facteurCaracterisations(referentielMapper.toListFacteurCaracterisation(calculOperationNonIT.getFacteurCaracterisations())) + .build(); + var impact = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalculImpactOperationNonIT); + if (impact != null) { + impactOperationNonITList.add(impact); + } + } + } + return impactOperationNonITList; + + } +} diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/IntegrationCalculEquipementsService.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/IntegrationCalculEquipementsService.java index 28a5d72b2d11c71c07aadd6f5a36c906ae47a2a2..1eff91ae2f216ca92e67cdea259a994cde814312 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/IntegrationCalculEquipementsService.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/IntegrationCalculEquipementsService.java @@ -57,7 +57,7 @@ public class IntegrationCalculEquipementsService { String nomEquipementPhysique = equipementPhysiqueDTO.getNomEquipementPhysique(); // delete existing indicateurs - indicateurRepository.clearIndicateurs(nomEquipementPhysique, nomLot); + indicateurRepository.clearIndicateursEquipement(nomEquipementPhysique, nomLot); var ttAfterClear = System.currentTimeMillis(); @@ -111,11 +111,11 @@ public class IntegrationCalculEquipementsService { totalNbApplication, ttAfterSaveStatus - ttStart, ttAfterClear - ttStart, - ttAfterFindEqV -ttAfterClear, + ttAfterFindEqV - ttAfterClear, ttAfterEqVAndApp - ttAfterFindEqV, ttAfterSave - ttAfterEqVAndApp, ttAfterSaveStatus - ttAfterSave - ); + ); CalculSizes result = new CalculSizes(); result.setNbEquipementPhysique(1); diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/IntegrationCalculOperationNonITService.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/IntegrationCalculOperationNonITService.java new file mode 100644 index 0000000000000000000000000000000000000000..6d6986738d273ea1ce0e1701c113b4d2af90e945 --- /dev/null +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/IntegrationCalculOperationNonITService.java @@ -0,0 +1,60 @@ +package org.mte.numecoeval.calculs.infrastructure.service.calcul; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.mte.numecoeval.calculs.domain.data.indicateurs.ImpactOperationNonIT; +import org.mte.numecoeval.calculs.domain.model.CalculOperationNonIT; +import org.mte.numecoeval.calculs.domain.model.CalculSizes; +import org.mte.numecoeval.calculs.infrastructure.repository.IndicateurRepository; +import org.mte.numecoeval.calculs.infrastructure.repository.OperationNonITRepository; +import org.mte.numecoeval.topic.data.OperationNonITDTO; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Slf4j +@Service +@AllArgsConstructor +public class IntegrationCalculOperationNonITService { + + IndicateurRepository indicateurRepository; + OperationNonITRepository operationNonITRepository; + CalculOperationNonITService calculOperationNonITService; + + /** + * Calcul les impacts d'une opération non IT + * + * @param calculOperationNonIT l'opération Non IT + * @return le nombre d'elements traites sous forme CalculSizes + */ + public CalculSizes calculImpactOperationNonIT(CalculOperationNonIT calculOperationNonIT) { + + if (calculOperationNonIT == null) return null; + + OperationNonITDTO operationNonITDTO = calculOperationNonIT.getOperationNonIT(); + String nomLot = operationNonITDTO.getNomLot(); + String nomOrganisation = operationNonITDTO.getNomOrganisation(); + String nomOperationNonIT = operationNonITDTO.getNomItemNonIT(); + + // delete existing indicateurs + indicateurRepository.clearIndicateursOperation(nomOperationNonIT, nomLot); + + List<ImpactOperationNonIT> impactOperationNonITList = calculOperationNonITService.calculImpactOperationNonIT(calculOperationNonIT); + + // save impacts into db + indicateurRepository.saveIndicateursOperationNonIT(impactOperationNonITList); + + // set statut of the operation to TRAITE + operationNonITRepository.setStatutToTraite(operationNonITDTO.getId()); + + log.info("{} - {} - {} : Calcul impacts opérations non IT: {}", + nomOrganisation, nomLot, operationNonITDTO.getDateLot(), + nomOperationNonIT + ); + + CalculSizes result = new CalculSizes(); + result.setNbOperationNonIT(1); + result.setNbIndicateurOperationNonIT(impactOperationNonITList.size()); + return result; + } +} \ No newline at end of file diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/MainOperationNonITService.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/MainOperationNonITService.java new file mode 100644 index 0000000000000000000000000000000000000000..8c042810a92758a9f4861b1fbdde180823c9a5c6 --- /dev/null +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/MainOperationNonITService.java @@ -0,0 +1,23 @@ +package org.mte.numecoeval.calculs.infrastructure.service.calcul; + +import lombok.AllArgsConstructor; +import org.mte.numecoeval.calculs.domain.model.CalculSizes; +import org.mte.numecoeval.calculs.infrastructure.service.enrichissement.EnrichissementOperationNonITService; +import org.mte.numecoeval.topic.data.OperationNonITDTO; +import org.springframework.stereotype.Service; + +@Service +@AllArgsConstructor +public class MainOperationNonITService { + + private EnrichissementOperationNonITService enrichissementOperationNonITService; + private IntegrationCalculOperationNonITService integrationCalculOperationNonITService; + + public CalculSizes calcul(OperationNonITDTO operationNonITDTO) { + + var eqPhEnrichi = enrichissementOperationNonITService.serviceEnrichissementOperationNonIT(operationNonITDTO); + return integrationCalculOperationNonITService.calculImpactOperationNonIT(eqPhEnrichi); + + } + +} diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/enrichissement/EnrichissementEquipementPhysiqueService.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/enrichissement/EnrichissementEquipementPhysiqueService.java index 1a23d86f413e12af269fa25a1b424d6a11af2520..73114e06370b5685d071933d6f88c5572e1d1ff1 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/enrichissement/EnrichissementEquipementPhysiqueService.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/enrichissement/EnrichissementEquipementPhysiqueService.java @@ -1,21 +1,26 @@ package org.mte.numecoeval.calculs.infrastructure.service.enrichissement; -import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.mte.numecoeval.calculs.domain.model.CalculEquipementPhysique; import org.mte.numecoeval.calculs.infrastructure.client.ReferentielClient; import org.mte.numecoeval.calculs.referentiels.generated.api.model.HypotheseDTO; import org.mte.numecoeval.topic.data.EquipementPhysiqueDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.util.ArrayList; +import java.util.Arrays; @Slf4j @Service -@AllArgsConstructor public class EnrichissementEquipementPhysiqueService { + @Value("${numecoeval.hypotheses.equipementPhysique}") + private String hypothesesEquipementPhysique; + + @Autowired private ReferentielClient referentielClient; public CalculEquipementPhysique serviceEnrichissementEquipementPhysique(EquipementPhysiqueDTO equipementPhysiqueDTO) { @@ -33,15 +38,12 @@ public class EnrichissementEquipementPhysiqueService { calculEquipementPhysique.setCriteres(referentielClient.getCriteres()); var hypotheses = new ArrayList<HypotheseDTO>(); - var hDuree = referentielClient.getHypothese("dureeVieParDefaut"); - var hPue = referentielClient.getHypothese("PUEParDefaut"); - var tuBYOD = referentielClient.getHypothese("taux_utilisation_BYOD"); - var tuCOPE = referentielClient.getHypothese("taux_utilisation_COPE"); - - if (hDuree != null) hypotheses.add(hDuree); - if (hPue != null) hypotheses.add(hPue); - if (tuBYOD != null) hypotheses.add(tuBYOD); - if (tuCOPE != null) hypotheses.add(tuCOPE); + + Arrays.stream(hypothesesEquipementPhysique.replaceAll(" +", "").split(",")) + .forEach(hypothese -> { + var h = referentielClient.getHypothese(hypothese); + if (h != null) hypotheses.add(h); + }); calculEquipementPhysique.setHypotheses(hypotheses); diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/enrichissement/EnrichissementOperationNonITService.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/enrichissement/EnrichissementOperationNonITService.java new file mode 100644 index 0000000000000000000000000000000000000000..e386fc9d020ed927499a789c258a4a12b9fd8a65 --- /dev/null +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/enrichissement/EnrichissementOperationNonITService.java @@ -0,0 +1,71 @@ +package org.mte.numecoeval.calculs.infrastructure.service.enrichissement; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.mte.numecoeval.calculs.domain.model.CalculOperationNonIT; +import org.mte.numecoeval.calculs.infrastructure.client.ReferentielClient; +import org.mte.numecoeval.calculs.referentiels.generated.api.model.HypotheseDTO; +import org.mte.numecoeval.topic.data.OperationNonITDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Arrays; + +@Slf4j +@Service +public class EnrichissementOperationNonITService { + + @Value("${numecoeval.hypotheses.operationNonIt}") + private String hypothesesOperationNonIt; + + @Autowired + private ReferentielClient referentielClient; + + public CalculOperationNonIT serviceEnrichissementOperationNonIT(OperationNonITDTO operationNonITDTO) { + if (operationNonITDTO == null) return null; + + log.debug("{} - {} - {} : Enrichissement d'une opération non IT : Nom Item: {}, Type: {}", + operationNonITDTO.getNomOrganisation(), operationNonITDTO.getNomLot(), operationNonITDTO.getDateLot(), + operationNonITDTO.getNomItemNonIT(), operationNonITDTO.getType()); + + CalculOperationNonIT calculOperationNonIT = new CalculOperationNonIT(); + + calculOperationNonIT.setOperationNonIT(operationNonITDTO); + + calculOperationNonIT.setEtapes(referentielClient.getEtapes()); + calculOperationNonIT.setCriteres(referentielClient.getCriteres()); + calculOperationNonIT.setTypeItem(referentielClient.getTypeItem(operationNonITDTO.getType())); + + var hypotheses = new ArrayList<HypotheseDTO>(); + var hTypeItem = referentielClient.getHypothese(referentielClient.getTypeItem(operationNonITDTO.getType()).getRefHypothese()); + if (hTypeItem != null) hypotheses.add(hTypeItem); + + Arrays.stream(hypothesesOperationNonIt.replaceAll(" +", "").split(",")) + .forEach(hypothese -> { + var h = referentielClient.getHypothese(hypothese); + if (h != null) hypotheses.add(h); + }); + + calculOperationNonIT.setHypotheses(hypotheses); + calculOperationNonIT.setFacteurCaracterisations(new ArrayList<>()); + + for (var critere : calculOperationNonIT.getCriteres()) { + for (var etape : calculOperationNonIT.getEtapes()) { + if (calculOperationNonIT.getTypeItem() != null && StringUtils.isNotBlank(calculOperationNonIT.getTypeItem().getRefItemParDefaut())) { + calculOperationNonIT.getFacteurCaracterisations().add( + referentielClient.getFacteurCaracterisationByCritereAndEtapeAndNom( + critere.getNomCritere(), + etape.getCode(), + calculOperationNonIT.getTypeItem().getRefItemParDefaut() + ) + ); + } + } + var mixElec = referentielClient.getMixElectriqueFromFacteurCaracterisation(critere.getNomCritere(), operationNonITDTO.getLocalisation()); + if (mixElec != null) calculOperationNonIT.getFacteurCaracterisations().add(mixElec); + } + return calculOperationNonIT; + } +} diff --git a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/sync/calculs/SyncCalculService.java b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/sync/calculs/SyncCalculService.java index 7afd35344fd1abee4707a2d308cf521b332fc464..5a84a5dcce49c707df48f0a6d6e2b8a701b85629 100644 --- a/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/sync/calculs/SyncCalculService.java +++ b/services/api-event-calculs/src/main/java/org/mte/numecoeval/calculs/infrastructure/service/sync/calculs/SyncCalculService.java @@ -4,8 +4,10 @@ import lombok.AllArgsConstructor; import org.mte.numecoeval.calculs.domain.model.CalculSizes; import org.mte.numecoeval.calculs.infrastructure.repository.EquipementPhysiqueRepository; import org.mte.numecoeval.calculs.infrastructure.repository.MessagerieRepository; +import org.mte.numecoeval.calculs.infrastructure.repository.OperationNonITRepository; import org.mte.numecoeval.calculs.infrastructure.service.calcul.MainEquipementPhysiqueService; import org.mte.numecoeval.calculs.infrastructure.service.calcul.MainMessagerieService; +import org.mte.numecoeval.calculs.infrastructure.service.calcul.MainOperationNonITService; import org.mte.numecoeval.calculs.sync.generated.api.model.ReponseCalculRest; import org.mte.numecoeval.calculs.sync.generated.api.model.SyncCalculRest; import org.springframework.stereotype.Service; @@ -18,11 +20,12 @@ import java.util.Objects; public class SyncCalculService { private EquipementPhysiqueRepository equipementPhysiqueRepository; + private OperationNonITRepository operationNonITRepository; private MessagerieRepository messagerieRepository; private MainEquipementPhysiqueService mainEquipementPhysiqueService; + private MainOperationNonITService mainOperationNonITService; private MainMessagerieService mainMessagerieService; - public ReponseCalculRest calcul(SyncCalculRest syncCalculRest) { var result = new ReponseCalculRest(); @@ -36,16 +39,20 @@ public class SyncCalculService { result.setNbrEquipementVirtuel(calculSizesList.stream().map(CalculSizes::getNbEquipementVirtuel).reduce(0L, Long::sum)); result.setNbrApplication(calculSizesList.stream().map(CalculSizes::getNbApplication).reduce(0L, Long::sum)); } - + if (syncCalculRest.getOperationNonITIds() != null && !syncCalculRest.getOperationNonITIds().isEmpty()) { + List<CalculSizes> calculSizesOperationNonITList = operationNonITRepository.findOperationNonITDTOs(syncCalculRest.getOperationNonITIds()).stream() + .map(operationNonITDTO -> mainOperationNonITService.calcul(operationNonITDTO)) + .filter(Objects::nonNull) + .toList(); + result.setNbrOperationNonIT(calculSizesOperationNonITList.stream().map(CalculSizes::getNbOperationNonIT).reduce(0L, Long::sum)); + } if (syncCalculRest.getMessagerieIds() != null && !syncCalculRest.getMessagerieIds().isEmpty()) { List<CalculSizes> calculSizesMessagerieList = messagerieRepository.findMessagerieDTOList(syncCalculRest.getMessagerieIds()).stream() .map(messagerieDTO -> mainMessagerieService.calcul(messagerieDTO)) .filter(Objects::nonNull) .toList(); - result.setNbrMessagerie(calculSizesMessagerieList.stream().map(CalculSizes::getNbMessagerie).reduce(0L, Long::sum)); } - return result; } } diff --git a/services/api-event-calculs/src/main/resources/application.yaml b/services/api-event-calculs/src/main/resources/application.yaml index 9be26cc42717c5b2bea44eace88446a76609714d..22e10dfe982e039d484f53aecc6710e8d631002a 100644 --- a/services/api-event-calculs/src/main/resources/application.yaml +++ b/services/api-event-calculs/src/main/resources/application.yaml @@ -30,9 +30,13 @@ spring: # Application numecoeval: + hypotheses: + equipementPhysique: "dureeVieParDefaut, PUEParDefaut, taux_utilisation_BYOD, taux_utilisation_COPE" + operationNonIt: "dureeVieParDefaut, PUEParDefaut, TAUX_VEHICULE_HYBRIDE, dureeVieBatimentParDefaut" topic: partition: "4" equipementPhysique: "entree_equipementPhysique" + operationNonIT: "entree_operationNonIT" messagerie: "entree_messagerie" referentiels: url: "http://localhost:18080" diff --git a/services/api-event-calculs/src/main/resources/schema.sql b/services/api-event-calculs/src/main/resources/schema.sql index c5b6cb8ea42e2ee86b292f2a5c2a022a66e8df3f..b95c0f3877f054fb2d0a4d4eef06adbf61a7c260 100644 --- a/services/api-event-calculs/src/main/resources/schema.sql +++ b/services/api-event-calculs/src/main/resources/schema.sql @@ -1,164 +1,170 @@ -- Creation des tables indicateurs CREATE TABLE IF NOT EXISTS ind_indicateur_impact_equipement_physique ( - date_calcul timestamp NULL, - date_lot date NULL, - nom_lot varchar(255) NULL, - etapeacv varchar(255) NULL, - critere varchar(255) NULL, - "source" varchar(255) NULL, - statut_indicateur varchar(255) NULL, - trace text NULL, - version_calcul varchar(255) NULL, - conso_elec_moyenne float8 NULL, - impact_unitaire float8 NULL, - quantite int4 NULL, - statut_equipement_physique varchar(255) NULL, - type_equipement varchar(255) NULL, - unite varchar(255) NULL, - nom_entite varchar(255) NULL, - nom_organisation varchar(255) NULL, - nom_source_donnee varchar(255) NULL, - nom_equipement varchar(255) NULL + date_calcul timestamp NULL, + date_lot date NULL, + nom_lot varchar(255) NULL, + etapeacv varchar(255) NULL, + critere varchar(255) NULL, + "source" varchar(255) NULL, + statut_indicateur varchar(255) NULL, + trace text NULL, + version_calcul varchar(255) NULL, + conso_elec_moyenne float8 NULL, + impact_unitaire float8 NULL, + quantite int4 NULL, + statut_equipement_physique varchar(255) NULL, + type_equipement varchar(255) NULL, + unite varchar(255) NULL, + nom_entite varchar(255) NULL, + nom_organisation varchar(255) NULL, + nom_source_donnee varchar(255) NULL, + nom_equipement varchar(255) NULL, + qualite varchar(255) NULL, + date_lot_discriminator date NOT NULL DEFAULT('1970-01-01'), + nom_organisation_discriminator varchar(255) NOT NULL DEFAULT(''), + nom_entite_discriminator varchar(255) NOT NULL DEFAULT(''), + nom_source_donnee_discriminator varchar(255) NOT NULL DEFAULT('') ); CREATE TABLE IF NOT EXISTS ind_indicateur_impact_equipement_virtuel ( - date_calcul timestamp NULL, - date_lot date NULL, - nom_lot varchar(255) NULL, - etapeacv varchar(255) NULL, - critere varchar(255) NULL, - nom_organisation varchar(255) NULL, - nom_source_donnee varchar(255) NULL, - nom_equipement varchar(255) NULL, - nom_equipement_virtuel varchar(255) NULL, - nom_entite varchar(255) NULL, - "source" varchar(255) NULL, - statut_indicateur varchar(255) NULL, - trace text NULL, - version_calcul varchar(255) NULL, - impact_unitaire float8 NULL, - unite varchar(255) NULL, - conso_elec_moyenne float8 NULL, - "cluster" varchar(255) NULL + date_calcul timestamp NULL, + date_lot date NULL, + nom_lot varchar(255) NULL, + etapeacv varchar(255) NULL, + critere varchar(255) NULL, + nom_organisation varchar(255) NULL, + nom_source_donnee varchar(255) NULL, + nom_equipement varchar(255) NULL, + nom_equipement_virtuel varchar(255) NULL, + nom_entite varchar(255) NULL, + "source" varchar(255) NULL, + statut_indicateur varchar(255) NULL, + trace text NULL, + version_calcul varchar(255) NULL, + impact_unitaire float8 NULL, + unite varchar(255) NULL, + conso_elec_moyenne float8 NULL, + "cluster" varchar(255) NULL, + qualite varchar(255) NULL, + date_lot_discriminator date NOT NULL DEFAULT('1970-01-01'), + nom_organisation_discriminator varchar(255) NOT NULL DEFAULT(''), + nom_entite_discriminator varchar(255) NOT NULL DEFAULT(''), + nom_source_donnee_discriminator varchar(255) NOT NULL DEFAULT('') ); CREATE TABLE IF NOT EXISTS ind_indicateur_impact_application ( - date_calcul timestamp NULL, - date_lot date NULL, - nom_lot varchar(255) NULL, - etapeacv varchar(255) NULL, - critere varchar(255) NULL, - nom_organisation varchar(255) NULL, - nom_source_donnee varchar(255) NULL, - nom_application varchar(255) NULL, - type_environnement varchar(255) NULL, - nom_equipement_physique varchar(255) NULL, - nom_equipement_virtuel varchar(255) NULL, - nom_entite varchar(255) NULL, - "source" varchar(255) NULL, - statut_indicateur varchar(255) NULL, - trace text NULL, - version_calcul varchar(255) NULL, - domaine varchar(255) NULL, - sous_domaine varchar(255) NULL, - impact_unitaire float8 NULL, - unite varchar(255) NULL, - conso_elec_moyenne float8 NULL + date_calcul timestamp NULL, + date_lot date NULL, + nom_lot varchar(255) NULL, + etapeacv varchar(255) NULL, + critere varchar(255) NULL, + nom_organisation varchar(255) NULL, + nom_source_donnee varchar(255) NULL, + nom_application varchar(255) NULL, + type_environnement varchar(255) NULL, + nom_equipement_physique varchar(255) NULL, + nom_equipement_virtuel varchar(255) NULL, + nom_entite varchar(255) NULL, + "source" varchar(255) NULL, + statut_indicateur varchar(255) NULL, + trace text NULL, + version_calcul varchar(255) NULL, + domaine varchar(255) NULL, + sous_domaine varchar(255) NULL, + impact_unitaire float8 NULL, + unite varchar(255) NULL, + conso_elec_moyenne float8 NULL, + qualite varchar(255) NULL, + date_lot_discriminator date NOT NULL DEFAULT('1970-01-01'), + nom_organisation_discriminator varchar(255) NOT NULL DEFAULT(''), + nom_entite_discriminator varchar(255) NOT NULL DEFAULT(''), + nom_source_donnee_discriminator varchar(255) NOT NULL DEFAULT('') +); + +CREATE TABLE IF NOT EXISTS ind_indicateur_impact_operation_non_it +( + date_calcul timestamp NULL, + date_lot date NULL, + nom_lot varchar(255) NULL, + etapeacv varchar(255) NULL, + critere varchar(255) NULL, + "source" varchar(255) NULL, + statut_indicateur varchar(255) NULL, + trace text NULL, + version_calcul varchar(255) NULL, + conso_elec_moyenne float8 NULL, + impact_unitaire float8 NULL, + quantite int4 NULL, + type_item varchar(255) NULL, + unite varchar(255) NULL, + nom_entite varchar(255) NULL, + nom_organisation varchar(255) NULL, + nom_source_donnee varchar(255) NULL, + nom_item_non_it varchar(255) NULL, + qualite varchar(255) NULL ); CREATE TABLE IF NOT EXISTS ind_indicateur_impact_messagerie ( - date_calcul timestamp NULL, - date_lot date NULL, - nom_lot varchar(255) NULL, - nom_organisation varchar(255) NULL, - nom_source_donnee varchar(255) NULL, - critere varchar(255) NULL, - mois_annee date NULL, - nom_entite varchar(255) NULL, - "source" varchar(255) NULL, - statut_indicateur varchar(255) NULL, - trace text NULL, - version_calcul varchar(255) NULL, - impact_mensuel float8 NULL, - unite varchar(255) NULL, - nombre_mail_emis float8 NULL, - volume_total_mail_emis float8 NULL + date_calcul timestamp NULL, + date_lot date NULL, + nom_lot varchar(255) NULL, + nom_organisation varchar(255) NULL, + nom_source_donnee varchar(255) NULL, + critere varchar(255) NULL, + mois_annee date NULL, + nom_entite varchar(255) NULL, + "source" varchar(255) NULL, + statut_indicateur varchar(255) NULL, + trace text NULL, + version_calcul varchar(255) NULL, + impact_mensuel float8 NULL, + unite varchar(255) NULL, + nombre_mail_emis float8 NULL, + volume_total_mail_emis float8 NULL, + date_lot_discriminator date NOT NULL DEFAULT('1970-01-01'), + nom_organisation_discriminator varchar(255) NOT NULL DEFAULT(''), + nom_entite_discriminator varchar(255) NOT NULL DEFAULT(''), + nom_source_donnee_discriminator varchar(255) NOT NULL DEFAULT('') ); CREATE TABLE IF NOT EXISTS ind_indicateur_impact_reseau ( - date_calcul timestamp NULL, - date_lot date NULL, - nom_lot varchar(255) NULL, - etapeacv varchar(255) NULL, - critere varchar(255) NULL, - "source" varchar(255) NULL, - statut_indicateur varchar(255) NULL, - trace text NULL, - version_calcul varchar(255) NULL, - impact_unitaire float8 NULL, - unite varchar(255) NULL, - nom_entite varchar(255) NULL, - nom_organisation varchar(255) NULL, - nom_source_donnee varchar(255) NULL, - nom_equipement varchar(255) NULL + date_calcul timestamp NULL, + date_lot date NULL, + nom_lot varchar(255) NULL, + etapeacv varchar(255) NULL, + critere varchar(255) NULL, + "source" varchar(255) NULL, + statut_indicateur varchar(255) NULL, + trace text NULL, + version_calcul varchar(255) NULL, + impact_unitaire float8 NULL, + unite varchar(255) NULL, + nom_entite varchar(255) NULL, + nom_organisation varchar(255) NULL, + nom_source_donnee varchar(255) NULL, + nom_equipement varchar(255) NULL, + date_lot_discriminator date NOT NULL DEFAULT('1970-01-01'), + nom_organisation_discriminator varchar(255) NOT NULL DEFAULT(''), + nom_entite_discriminator varchar(255) NOT NULL DEFAULT(''), + nom_source_donnee_discriminator varchar(255) NOT NULL DEFAULT('') ); -ALTER TABLE IF EXISTS ind_indicateur_impact_equipement_physique ADD COLUMN IF NOT EXISTS date_lot_discriminator DATE NOT NULL DEFAULT '1970-01-01'; -UPDATE ind_indicateur_impact_equipement_physique SET date_lot_discriminator = coalesce(date_lot, '1970-01-01') where date_lot_discriminator is null; -ALTER TABLE IF EXISTS ind_indicateur_impact_reseau ADD COLUMN IF NOT EXISTS date_lot_discriminator DATE NOT NULL DEFAULT '1970-01-01'; -UPDATE ind_indicateur_impact_reseau SET date_lot_discriminator = coalesce(date_lot, '1970-01-01') where date_lot_discriminator is null; -ALTER TABLE IF EXISTS ind_indicateur_impact_equipement_virtuel ADD COLUMN IF NOT EXISTS date_lot_discriminator DATE NOT NULL DEFAULT '1970-01-01'; -UPDATE ind_indicateur_impact_equipement_virtuel SET date_lot_discriminator = coalesce(date_lot, '1970-01-01') where date_lot_discriminator is null; -ALTER TABLE IF EXISTS ind_indicateur_impact_application ADD COLUMN IF NOT EXISTS date_lot_discriminator DATE NOT NULL DEFAULT '1970-01-01'; -UPDATE ind_indicateur_impact_application SET date_lot_discriminator = coalesce(date_lot, '1970-01-01') where date_lot_discriminator is null; -ALTER TABLE IF EXISTS ind_indicateur_impact_messagerie ADD COLUMN IF NOT EXISTS date_lot_discriminator DATE NOT NULL DEFAULT '1970-01-01'; -UPDATE ind_indicateur_impact_messagerie SET date_lot_discriminator = coalesce(date_lot, '1970-01-01') where date_lot_discriminator is null; - -ALTER TABLE IF EXISTS ind_indicateur_impact_equipement_physique ADD COLUMN IF NOT EXISTS nom_organisation_discriminator varchar(255) NOT NULL DEFAULT ''; -ALTER TABLE IF EXISTS ind_indicateur_impact_equipement_physique ALTER COLUMN nom_organisation_discriminator SET NOT NULL; -ALTER TABLE IF EXISTS ind_indicateur_impact_reseau ADD COLUMN IF NOT EXISTS nom_organisation_discriminator varchar(255) NOT NULL DEFAULT ''; -ALTER TABLE IF EXISTS ind_indicateur_impact_reseau ALTER COLUMN nom_organisation_discriminator SET NOT NULL; -ALTER TABLE IF EXISTS ind_indicateur_impact_equipement_virtuel ADD COLUMN IF NOT EXISTS nom_organisation_discriminator varchar(255) NOT NULL DEFAULT ''; -ALTER TABLE IF EXISTS ind_indicateur_impact_equipement_virtuel ALTER COLUMN nom_organisation_discriminator SET NOT NULL; -ALTER TABLE IF EXISTS ind_indicateur_impact_application ADD COLUMN IF NOT EXISTS nom_organisation_discriminator varchar(255) NOT NULL DEFAULT ''; -ALTER TABLE IF EXISTS ind_indicateur_impact_application ALTER COLUMN nom_organisation_discriminator SET NOT NULL; -ALTER TABLE IF EXISTS ind_indicateur_impact_messagerie ADD COLUMN IF NOT EXISTS nom_organisation_discriminator varchar(255) NOT NULL DEFAULT ''; -ALTER TABLE IF EXISTS ind_indicateur_impact_messagerie ALTER COLUMN nom_organisation_discriminator SET NOT NULL; - -ALTER TABLE IF EXISTS ind_indicateur_impact_equipement_physique ADD COLUMN IF NOT EXISTS nom_entite_discriminator varchar(255) NOT NULL DEFAULT ''; -UPDATE ind_indicateur_impact_equipement_physique SET nom_entite_discriminator = coalesce(nom_entite, '') where nom_entite_discriminator is null; -ALTER TABLE IF EXISTS ind_indicateur_impact_reseau ADD COLUMN IF NOT EXISTS nom_entite_discriminator varchar(255) NOT NULL DEFAULT ''; -UPDATE ind_indicateur_impact_reseau SET nom_entite_discriminator = coalesce(nom_entite, '') where nom_entite_discriminator is null; -ALTER TABLE IF EXISTS ind_indicateur_impact_equipement_virtuel ADD COLUMN IF NOT EXISTS nom_entite_discriminator varchar(255) NOT NULL DEFAULT ''; -UPDATE ind_indicateur_impact_equipement_virtuel SET nom_entite_discriminator = coalesce(nom_entite, '') where nom_entite_discriminator is null; -ALTER TABLE IF EXISTS ind_indicateur_impact_application ADD COLUMN IF NOT EXISTS nom_entite_discriminator varchar(255) NOT NULL DEFAULT ''; -UPDATE ind_indicateur_impact_application SET nom_entite_discriminator = coalesce(nom_entite, '') where nom_entite_discriminator is null; -ALTER TABLE IF EXISTS ind_indicateur_impact_messagerie ADD COLUMN IF NOT EXISTS nom_entite_discriminator varchar(255) NOT NULL DEFAULT ''; -UPDATE ind_indicateur_impact_messagerie SET nom_entite_discriminator = coalesce(nom_entite, '') where nom_entite_discriminator is null; - -ALTER TABLE IF EXISTS ind_indicateur_impact_equipement_physique ADD COLUMN IF NOT EXISTS nom_source_donnee_discriminator varchar(255) NOT NULL DEFAULT ''; -UPDATE ind_indicateur_impact_equipement_physique SET nom_source_donnee_discriminator = coalesce(nom_source_donnee, '') where nom_source_donnee_discriminator is null; -ALTER TABLE IF EXISTS ind_indicateur_impact_reseau ADD COLUMN IF NOT EXISTS nom_source_donnee_discriminator varchar(255) NOT NULL DEFAULT ''; -UPDATE ind_indicateur_impact_reseau SET nom_source_donnee_discriminator = coalesce(nom_source_donnee, '') where nom_source_donnee_discriminator is null; -ALTER TABLE IF EXISTS ind_indicateur_impact_equipement_virtuel ADD COLUMN IF NOT EXISTS nom_source_donnee_discriminator varchar(255) NOT NULL DEFAULT ''; -UPDATE ind_indicateur_impact_equipement_virtuel SET nom_source_donnee_discriminator = coalesce(nom_source_donnee, '') where nom_source_donnee_discriminator is null; -ALTER TABLE IF EXISTS ind_indicateur_impact_application ADD COLUMN IF NOT EXISTS nom_source_donnee_discriminator varchar(255) NOT NULL DEFAULT ''; -UPDATE ind_indicateur_impact_application SET nom_source_donnee_discriminator = coalesce(nom_source_donnee, '') where nom_source_donnee_discriminator is null; -ALTER TABLE IF EXISTS ind_indicateur_impact_messagerie ADD COLUMN IF NOT EXISTS nom_source_donnee_discriminator varchar(255) NOT NULL DEFAULT ''; -UPDATE ind_indicateur_impact_messagerie SET nom_source_donnee_discriminator = coalesce(nom_source_donnee, '') where nom_source_donnee_discriminator is null; - +ALTER TABLE IF EXISTS ind_indicateur_impact_equipement_physique ADD COLUMN IF NOT EXISTS qualite varchar(255) NULL DEFAULT ''; +ALTER TABLE IF EXISTS ind_indicateur_impact_application ADD COLUMN IF NOT EXISTS qualite varchar(255) NULL DEFAULT ''; +ALTER TABLE IF EXISTS ind_indicateur_impact_equipement_virtuel ADD COLUMN IF NOT EXISTS qualite varchar(255) NULL DEFAULT ''; +ALTER TABLE IF EXISTS ind_indicateur_impact_operation_non_it ADD COLUMN IF NOT EXISTS qualite varchar(255) NULL DEFAULT ''; CREATE INDEX IF NOT EXISTS idx_ind_eq_p__nom_lot_nom_equipement ON ind_indicateur_impact_equipement_physique (nom_lot, nom_equipement); CREATE INDEX IF NOT EXISTS idx_ind_eq_v__nom_lot_nom_equipement ON ind_indicateur_impact_equipement_virtuel (nom_lot, nom_equipement); CREATE INDEX IF NOT EXISTS idx_ind_app__nom_lot_nom_equipement ON ind_indicateur_impact_application (nom_lot, nom_equipement_physique); CREATE INDEX IF NOT EXISTS idx_ind_reseau__nom_lot_nom_equipement ON ind_indicateur_impact_reseau (nom_lot, nom_equipement); +CREATE INDEX IF NOT EXISTS idx_ind_operation_non_it__nom_lot_nom_item_non_it ON ind_indicateur_impact_operation_non_it (nom_lot, nom_item_non_it); -- Lignes a supprimer dans les futures versions ALTER TABLE ind_indicateur_impact_equipement_virtuel ADD COLUMN IF NOT EXISTS nom_equipement_virtuel VARCHAR(255); ALTER TABLE ind_indicateur_impact_application ADD COLUMN IF NOT EXISTS nom_equipement_virtuel VARCHAR(255); - diff --git a/services/api-event-calculs/src/test/java/org/mte/numecoeval/calculs/ApiEventCalculsApplicationTests.java b/services/api-event-calculs/src/test/java/org/mte/numecoeval/calculs/ApiEventCalculsApplicationTests.java index 9c4949fd14d524a72e63c6ba0ef7aba2f6124de7..4310c44079d6a92dd53ad178ec7b3f46bb86bfab 100644 --- a/services/api-event-calculs/src/test/java/org/mte/numecoeval/calculs/ApiEventCalculsApplicationTests.java +++ b/services/api-event-calculs/src/test/java/org/mte/numecoeval/calculs/ApiEventCalculsApplicationTests.java @@ -54,6 +54,8 @@ class ApiEventCalculsApplicationTests { @MockBean ApplicationRepository applicationRepository; @MockBean + DonneesEntreeRepository donneesEntreeRepository; + @MockBean MessagerieRepository messagerieRepository; @MockBean DataSource dataSource; diff --git a/services/api-event-calculs/src/test/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/EnrichissementEquipementPhysiqueServiceTest.java b/services/api-event-calculs/src/test/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/EnrichissementEquipementPhysiqueServiceTest.java index 9751e08259dda7214b9e85b678b2d9cd11d22e0f..579474dced27d915e198073f3a63d76d6876f241 100644 --- a/services/api-event-calculs/src/test/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/EnrichissementEquipementPhysiqueServiceTest.java +++ b/services/api-event-calculs/src/test/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/EnrichissementEquipementPhysiqueServiceTest.java @@ -15,13 +15,19 @@ import org.mte.numecoeval.calculs.infrastructure.client.ReferentielClient; import org.mte.numecoeval.calculs.infrastructure.service.enrichissement.EnrichissementEquipementPhysiqueService; import org.mte.numecoeval.calculs.referentiels.generated.api.model.*; import org.mte.numecoeval.topic.data.EquipementPhysiqueDTO; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.util.ReflectionTestUtils; import java.util.Arrays; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; -@ExtendWith(MockitoExtension.class) +@ExtendWith({MockitoExtension.class, SpringExtension.class}) +@ContextConfiguration(initializers = ConfigDataApplicationContextInitializer.class) class EnrichissementEquipementPhysiqueServiceTest { private static final ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule()); @@ -32,6 +38,9 @@ class EnrichissementEquipementPhysiqueServiceTest { @Mock ReferentielClient referentielClient; + @Value("${numecoeval.hypotheses.equipementPhysique}") + private String hypothesesEquipementPhysique; + EquipementPhysiqueDTO equipementPhysiqueDTO = mapper.readValue(""" { "id": 43702, @@ -61,7 +70,8 @@ class EnrichissementEquipementPhysiqueServiceTest { "localisation": "France", "dateLot": "2023-10-26", "nomOrganisation": "org" - } + }, + "qualite":"HAUTE" } """, EquipementPhysiqueDTO.class); @@ -70,6 +80,8 @@ class EnrichissementEquipementPhysiqueServiceTest { @BeforeEach void initMocksReferentiel() throws JsonProcessingException { + ReflectionTestUtils.setField(enrichissementEquipementPhysiqueService, "hypothesesEquipementPhysique", hypothesesEquipementPhysique); + /* MOCK REFERENTIEL : Etapes */ Mockito.lenient().when(referentielClient.getEtapes()).thenReturn(Arrays.asList(mapper.readValue(""" [{ "code": "UTILISATION", "libelle": "Using" }] @@ -133,6 +145,7 @@ class EnrichissementEquipementPhysiqueServiceTest { Assertions.assertEquals(1, actual.getMixElectriques().size()); Assertions.assertEquals("FR", actual.getMixElectriques().get(0).getPays()); Assertions.assertEquals(1.1, actual.getImpactsEquipement().get(0).getValeur()); + Assertions.assertEquals("HAUTE", actual.getEquipementPhysique().getQualite()); } @@ -160,5 +173,6 @@ class EnrichissementEquipementPhysiqueServiceTest { Assertions.assertEquals(1, actual.getMixElectriques().size()); Assertions.assertEquals("FR", actual.getMixElectriques().get(0).getPays()); Assertions.assertEquals(2.2, actual.getImpactsEquipement().get(0).getValeur()); + Assertions.assertEquals("HAUTE", actual.getEquipementPhysique().getQualite()); } } diff --git a/services/api-event-calculs/src/test/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/EnrichissementOperationNonITServiceTest.java b/services/api-event-calculs/src/test/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/EnrichissementOperationNonITServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..55f4b3872c65d3f641c321655226f2d4f9c13aa0 --- /dev/null +++ b/services/api-event-calculs/src/test/java/org/mte/numecoeval/calculs/infrastructure/service/calcul/EnrichissementOperationNonITServiceTest.java @@ -0,0 +1,153 @@ +package org.mte.numecoeval.calculs.infrastructure.service.calcul; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mte.numecoeval.calculs.infrastructure.client.ReferentielClient; +import org.mte.numecoeval.calculs.infrastructure.service.enrichissement.EnrichissementOperationNonITService; +import org.mte.numecoeval.calculs.referentiels.generated.api.model.*; +import org.mte.numecoeval.topic.data.OperationNonITDTO; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.util.ReflectionTestUtils; + +import java.util.Arrays; + +import static org.junit.jupiter.api.Assertions.assertNull; + +@ExtendWith({MockitoExtension.class, SpringExtension.class}) +@ContextConfiguration(initializers = ConfigDataApplicationContextInitializer.class) +class EnrichissementOperationNonITServiceTest { + + private static final ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule()); + + @InjectMocks + EnrichissementOperationNonITService enrichissementOperationNonITService; + + @Mock + ReferentielClient referentielClient; + + @Value("${numecoeval.hypotheses.operationNonIt}") + private String hypothesesOperationNonIt; + + OperationNonITDTO operationNonITDTO = mapper.readValue(""" + { + "id": 43701, + "nomItemNonIT": "reseau-fixe-rennes", + "quantite": 7.0, + "type": "reseau-fixe-france", + "dureeDeVie": 27.0, + "localisation": "France", + "nomEntite": "Entite test", + "nomSourceDonnee":"RCP-SI", + "nomCourtDatacenter": "dc1", + "description": "voici une description", + "consoElecAnnuelle": null, + "nomLot": "lot1", + "dateLot": "2024-04-24", + "nomOrganisation": "org", + "qualite":"BASSE" + } + """, OperationNonITDTO.class); + + EnrichissementOperationNonITServiceTest() throws JsonProcessingException { + } + + @BeforeEach + void initMocksReferentiel() throws JsonProcessingException { + ReflectionTestUtils.setField(enrichissementOperationNonITService, "hypothesesOperationNonIt", hypothesesOperationNonIt); + + /* MOCK REFERENTIEL : Etapes */ + Mockito.lenient().when(referentielClient.getEtapes()).thenReturn(Arrays.asList(mapper.readValue(""" + [{ "code": "UTILISATION", "libelle": "Using" }] + """, EtapeDTO[].class))); + + /* MOCK REFERENTIEL : Criteres */ + Mockito.lenient().when(referentielClient.getCriteres()).thenReturn(Arrays.asList(mapper.readValue(""" + [{ + "nomCritere": "Climate change", + "unite": "kg CO2 eq", + "description": "Greenhouse gases (GHG)" + }] + """, CritereDTO[].class))); + + /* MOCK REFERENTIEL : Hypothese */ + Mockito.lenient().when(referentielClient.getHypothese("CAPACITE_LIGNE_FIXE_FR")).thenReturn(mapper.readValue(""" + { + "code": "CAPACITE_LIGNE_FIXE_FR", + "valeur": 2640, + "source": "Rapport ADEME" + } + """, HypotheseDTO.class)); + + /* MOCK REFERENTIEL : TypeItem */ + Mockito.lenient().when(referentielClient.getTypeItem("reseau-fixe-france")).thenReturn(mapper.readValue(""" + { + "type": "reseau-fixe-france", + "categorie" : "RESEAU_FIXE", + "refHypothese" : "CAPACITE_LIGNE_FIXE_FR", + "refItemParDefaut" : "reseau-fixe-1" + } + """, TypeItemDTO.class)); + + /* MOCK REFERENTIEL : FacteurCaracterisation */ + Mockito.lenient().when(referentielClient.getFacteurCaracterisationByCritereAndEtapeAndNom("Climate change", "UTILISATION", "reseau-fixe-1")).thenReturn(mapper.readValue(""" + { + "nom": "reseau-fixe-1", + "etape" : "UTILISATION", + "critere" : "Climate change", + "localisation": "France", + "consoElecMoyenne": 12.7, + "valeur" : "8.34" + } + """, FacteurCaracterisationDTO.class)); + + /* MOCK REFERENTIEL : MixElectrique */ + Mockito.lenient().when(referentielClient.getMixElectriqueFromFacteurCaracterisation("Climate change", "France")).thenReturn(mapper.readValue(""" + { + "nom": "Electricity Mix/ Production mix/ Low voltage/ CL", + "etape" : "FABRICATION", + "critere" : "Climate change", + "categorie" : "electricity-mix", + "localisation": "France", + "valeur" : "0.0813225" + } + """, FacteurCaracterisationDTO.class)); + } + + @Test + void testServiceEnrichissementOperationNonIT_null() { + assertNull(enrichissementOperationNonITService.serviceEnrichissementOperationNonIT(null)); + } + + @Test + void testServiceEnrichissementOperationNonIT_via_typeItem() throws JsonProcessingException { + + var actual = enrichissementOperationNonITService.serviceEnrichissementOperationNonIT(operationNonITDTO); + + Assertions.assertEquals(1, actual.getEtapes().size()); + Assertions.assertEquals(1, actual.getCriteres().size()); + Assertions.assertEquals(1, actual.getHypotheses().size()); + + Assertions.assertEquals(2, actual.getFacteurCaracterisations().size()); + + Assertions.assertEquals("reseau-fixe-1", actual.getFacteurCaracterisations().get(0).getNom()); + Assertions.assertEquals(12.7, actual.getFacteurCaracterisations().get(0).getConsoElecMoyenne()); + Assertions.assertEquals(8.34, actual.getFacteurCaracterisations().get(0).getValeur()); + + Assertions.assertEquals("France", actual.getFacteurCaracterisations().get(1).getLocalisation()); + Assertions.assertEquals(0.0813225, actual.getFacteurCaracterisations().get(1).getValeur()); + Assertions.assertEquals("BASSE", actual.getOperationNonIT().getQualite()); + + } +} diff --git a/services/api-event-calculs/src/test/java/org/mte/numecoeval/calculs/infrastructure/service/sync/calculs/SyncCalculServiceTest.java b/services/api-event-calculs/src/test/java/org/mte/numecoeval/calculs/infrastructure/service/sync/calculs/SyncCalculServiceTest.java index a32cfcdff34b00a8fa1e39f917a41b16cbacde38..8e601d8f5d7d0305ecb8882f18a7f147336ec6c8 100644 --- a/services/api-event-calculs/src/test/java/org/mte/numecoeval/calculs/infrastructure/service/sync/calculs/SyncCalculServiceTest.java +++ b/services/api-event-calculs/src/test/java/org/mte/numecoeval/calculs/infrastructure/service/sync/calculs/SyncCalculServiceTest.java @@ -13,11 +13,14 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.mte.numecoeval.calculs.domain.model.CalculSizes; import org.mte.numecoeval.calculs.infrastructure.repository.EquipementPhysiqueRepository; import org.mte.numecoeval.calculs.infrastructure.repository.MessagerieRepository; +import org.mte.numecoeval.calculs.infrastructure.repository.OperationNonITRepository; import org.mte.numecoeval.calculs.infrastructure.service.calcul.MainEquipementPhysiqueService; import org.mte.numecoeval.calculs.infrastructure.service.calcul.MainMessagerieService; +import org.mte.numecoeval.calculs.infrastructure.service.calcul.MainOperationNonITService; import org.mte.numecoeval.calculs.sync.generated.api.model.SyncCalculRest; import org.mte.numecoeval.topic.data.EquipementPhysiqueDTO; import org.mte.numecoeval.topic.data.MessagerieDTO; +import org.mte.numecoeval.topic.data.OperationNonITDTO; import java.util.List; @@ -33,7 +36,10 @@ class SyncCalculServiceTest { EquipementPhysiqueRepository equipementPhysiqueRepository; @Mock MainEquipementPhysiqueService mainEquipementPhysiqueService; - + @Mock + OperationNonITRepository operationNonITRepository; + @Mock + MainOperationNonITService mainOperationNonITService; @Mock MessagerieRepository messagerieRepository; @Mock @@ -91,4 +97,29 @@ class SyncCalculServiceTest { /* ASSERT */ Assertions.assertEquals(3, actual.getNbrMessagerie()); } + + @Test + void testSyncCalculService_withListOperationNonIT() throws JsonProcessingException { + /* MOCKS */ + Mockito.when(operationNonITRepository.findOperationNonITDTOs(any())).thenReturn(List.of( + new OperationNonITDTO(), + new OperationNonITDTO() + )); + + var calculSizes = new CalculSizes(); + calculSizes.setNbOperationNonIT(1); + calculSizes.setNbEquipementVirtuel(2); + calculSizes.setNbApplication(3); + + Mockito.when(mainOperationNonITService.calcul(any())).thenReturn(calculSizes); + + var syncCalculRest = new SyncCalculRest(); + syncCalculRest.setOperationNonITIds(List.of(1L, 2L)); + + /* EXECUTE */ + var actual = syncCalculService.calcul(syncCalculRest); + + /* ASSERT */ + Assertions.assertEquals(2, actual.getNbrOperationNonIT()); + } } diff --git a/services/api-event-donneesentrees/pom.xml b/services/api-event-donneesentrees/pom.xml index fddd0cabec60b968a95dfe5d2fc56cbc9317e7b9..ca37006212cceab4ad0df13f471f475391e0d655 100644 --- a/services/api-event-donneesentrees/pom.xml +++ b/services/api-event-donneesentrees/pom.xml @@ -5,12 +5,12 @@ <parent> <groupId>org.mte.numecoeval</groupId> <artifactId>core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <artifactId>api-event-donneesEntrees</artifactId> <name>api-event-donneesEntrees</name> - <version>1.3.0</version> + <version>1.4.0</version> <description>api-event-donneesEntrees</description> <repositories> diff --git a/services/api-event-donneesentrees/src/main/java/org/mte/numecoeval/donneesentrees/infrastructure/config/EquipementPhysiqueIntegrationConfig.java b/services/api-event-donneesentrees/src/main/java/org/mte/numecoeval/donneesentrees/infrastructure/config/EquipementPhysiqueIntegrationConfig.java index d7a8dc6965bedc51fa790582d478b4c28b9099a9..b85346829c63b87f4b519f9335e4d289e4931408 100644 --- a/services/api-event-donneesentrees/src/main/java/org/mte/numecoeval/donneesentrees/infrastructure/config/EquipementPhysiqueIntegrationConfig.java +++ b/services/api-event-donneesentrees/src/main/java/org/mte/numecoeval/donneesentrees/infrastructure/config/EquipementPhysiqueIntegrationConfig.java @@ -84,7 +84,7 @@ public class EquipementPhysiqueIntegrationConfig { @Bean @InboundChannelAdapter( value = "entreeEquipementPhysiqueSplitter", - poller = @Poller(fixedDelay = "5000") + poller = @Poller(fixedDelay = "1000") ) @SuppressWarnings("java:S1452") // La classe JdbcPollingChannelAdapter n'est pas compatible avec une classe fixe public MessageSource<?> getEquipementPhysiqueToProcess(DataSource dataSource) { @@ -97,7 +97,8 @@ public class EquipementPhysiqueIntegrationConfig { dc.localisation as dc_localisation, dc.nom_long_datacenter as dc_nom_long_datacenter, dc.pue as dc_pue, - dc.nom_entite as dc_nom_entite + dc.nom_entite as dc_nom_entite, + dc.qualite as dc_qualite FROM en_equipement_physique eqp LEFT JOIN en_data_center dc ON dc.nom_lot = eqp.nom_lot and dc.nom_court_datacenter = eqp.nom_court_datacenter WHERE eqp.statut_traitement = 'A_INGERER' @@ -117,6 +118,9 @@ public class EquipementPhysiqueIntegrationConfig { .consoElecAnnuelle(ResultSetUtils.getDouble(rs, "conso_elec_annuelle")) .dateAchat(ResultSetUtils.getLocalDate(rs, "date_achat")) .dateRetrait(ResultSetUtils.getLocalDate(rs, "date_retrait")) + .dureeUsageInterne(ResultSetUtils.getDouble(rs, "duree_usage_interne")) + .dureeUsageAmont(ResultSetUtils.getDouble(rs, "duree_usage_amont")) + .dureeUsageAval(ResultSetUtils.getDouble(rs, "duree_usage_aval")) .goTelecharge(ResultSetUtils.getFloat(rs, "go_telecharge")) .modele(rs.getString("modele")) .nbCoeur(rs.getString("nb_coeur")) @@ -130,6 +134,7 @@ public class EquipementPhysiqueIntegrationConfig { .utilisateur(rs.getString("utilisateur")) .nomCourtDatacenter(rs.getString(COLUMN_NAME_NOM_COURT_DATACENTER)) .nomSourceDonnee(rs.getString("nom_source_donnee")) + .qualite(rs.getString("qualite")) .dataCenter( DataCenterDTO.builder() .id(rs.getLong("dc_id")) @@ -140,6 +145,7 @@ public class EquipementPhysiqueIntegrationConfig { .nomEntite(rs.getString("dc_nom_entite")) .nomOrganisation(rs.getString("nom_organisation")) .dateLot(ResultSetUtils.getLocalDate(rs, "date_lot")) + .qualite(rs.getString("dc_qualite")) .build() ) .build() diff --git a/services/api-event-donneesentrees/src/main/java/org/mte/numecoeval/donneesentrees/infrastructure/config/MessagerieIntegrationConfig.java b/services/api-event-donneesentrees/src/main/java/org/mte/numecoeval/donneesentrees/infrastructure/config/MessagerieIntegrationConfig.java index 371fa3d976269198c7f976aa0a10f2162bb97e98..8cef865fa42a97e588a289587356d6842ce18d2a 100644 --- a/services/api-event-donneesentrees/src/main/java/org/mte/numecoeval/donneesentrees/infrastructure/config/MessagerieIntegrationConfig.java +++ b/services/api-event-donneesentrees/src/main/java/org/mte/numecoeval/donneesentrees/infrastructure/config/MessagerieIntegrationConfig.java @@ -69,7 +69,7 @@ public class MessagerieIntegrationConfig { @Bean @InboundChannelAdapter( value = "entreeMessagerieSplitter", - poller = @Poller(fixedDelay = "5000") + poller = @Poller(fixedDelay = "1000") ) @SuppressWarnings("java:S1452") // La classe JdbcPollingChannelAdapter n'est pas compatible avec une classe fixe public MessageSource<?> getMessagerieToProcess(DataSource dataSource) { diff --git a/services/api-event-donneesentrees/src/main/java/org/mte/numecoeval/donneesentrees/infrastructure/config/OperationNonITIntegrationConfig.java b/services/api-event-donneesentrees/src/main/java/org/mte/numecoeval/donneesentrees/infrastructure/config/OperationNonITIntegrationConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..bde9876c3bf09b8026d4ee23fadd8395a4500c38 --- /dev/null +++ b/services/api-event-donneesentrees/src/main/java/org/mte/numecoeval/donneesentrees/infrastructure/config/OperationNonITIntegrationConfig.java @@ -0,0 +1,139 @@ +package org.mte.numecoeval.donneesentrees.infrastructure.config; + +import lombok.extern.slf4j.Slf4j; +import org.apache.kafka.clients.admin.NewTopic; +import org.mte.numecoeval.common.utils.ResultSetUtils; +import org.mte.numecoeval.donneesentrees.infrastructure.utils.Constants; +import org.mte.numecoeval.topic.data.OperationNonITDTO; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.expression.common.LiteralExpression; +import org.springframework.integration.annotation.InboundChannelAdapter; +import org.springframework.integration.annotation.Poller; +import org.springframework.integration.annotation.ServiceActivator; +import org.springframework.integration.annotation.Splitter; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.core.MessageSource; +import org.springframework.integration.expression.FunctionExpression; +import org.springframework.integration.expression.ValueExpression; +import org.springframework.integration.jdbc.JdbcPollingChannelAdapter; +import org.springframework.integration.kafka.outbound.KafkaProducerMessageHandler; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.messaging.Message; +import org.springframework.messaging.MessageChannel; +import org.springframework.messaging.MessageHandler; +import org.springframework.messaging.support.GenericMessage; + +import javax.sql.DataSource; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.function.Function; + +@Slf4j +@Configuration +@ConditionalOnProperty( + value = "numecoeval.features.opnit" +) +public class OperationNonITIntegrationConfig { + + private static final String COLUMN_NAME_NOM_COURT_DATACENTER = "nom_court_datacenter"; + + @Value("${numecoeval.topic.entree.operationNonIT}") + String topicEntreeOperationNonIT; + + @Value("${numecoeval.topic.partition}") + Integer topicPartition; + + /** + * Topic Kafka pour les opérationsNonIT + * + * @return Topic à créer dans Kafka + */ + @Bean + public NewTopic topicEntreeOperationNonIT() { + return new NewTopic(topicEntreeOperationNonIT, topicPartition, (short) 1); + } + + @Bean + public MessageChannel entreeOperationNonIT() { + return new DirectChannel(); + } + + @Bean + public MessageChannel entreeOperationNonITSplitter() { + return new DirectChannel(); + } + + @Bean + @ServiceActivator(inputChannel = "entreeOperationNonIT") + public MessageHandler operationNonITHandler(KafkaTemplate<String, OperationNonITDTO> kafkaTemplate) { + KafkaProducerMessageHandler<String, OperationNonITDTO> handler = + new KafkaProducerMessageHandler<>(kafkaTemplate); + handler.setMessageKeyExpression(new LiteralExpression(UUID.randomUUID().toString())); + handler.setTopicExpression(new ValueExpression<>(topicEntreeOperationNonIT)); + Function<Message<?>, Long> partitionIdRandomFn = (m) -> (long) (Math.random() * topicPartition); + handler.setPartitionIdExpression(new FunctionExpression<>(partitionIdRandomFn)); + return handler; + } + + @Bean + @InboundChannelAdapter( + value = "entreeOperationNonITSplitter", + poller = @Poller(fixedDelay = "1000") + ) + @SuppressWarnings("java:S1452") // La classe JdbcPollingChannelAdapter n'est pas compatible avec une classe fixe + public MessageSource<?> getOperationNonITToProcess(DataSource dataSource) { + JdbcPollingChannelAdapter adapter = new JdbcPollingChannelAdapter(dataSource, + """ + SELECT * + FROM en_operation_non_it + WHERE statut_traitement = 'A_INGERER' + ORDER BY nom_lot ASC, date_lot ASC, nom_organisation ASC + LIMIT 1000 + """ + ); + adapter.setUpdateSql("UPDATE en_operation_non_it SET statut_traitement = 'INGERE', date_update = now() WHERE id in (:id)"); + adapter.setRowMapper((rs, index) -> + OperationNonITDTO.builder() + .id(rs.getLong("id")) + .nomLot(rs.getString("nom_lot")) + .dateLot(ResultSetUtils.getLocalDate(rs, "date_lot")) + .nomOrganisation(rs.getString("nom_organisation")) + .nomItemNonIT(rs.getString("nom_item_non_it")) + .quantite(ResultSetUtils.getDouble(rs, "quantite")) + .type(rs.getString("type")) + .dureeDeVie(ResultSetUtils.getDouble(rs, "duree_de_vie")) + .localisation(rs.getString("localisation")) + .nomEntite(rs.getString("nom_entite")) + .nomSourceDonnee(rs.getString("nom_source_donnee")) + .nomCourtDatacenter(rs.getString(COLUMN_NAME_NOM_COURT_DATACENTER)) + .description(rs.getString("description")) + .consoElecAnnuelle(ResultSetUtils.getDouble(rs, "conso_elec_annuelle")) + .qualite(rs.getString("qualite")) + .build() + ); + return adapter; + } + + @Splitter( + inputChannel = "entreeOperationNonITSplitter", + outputChannel = "entreeOperationNonIT" + ) + public List<Message<OperationNonITDTO>> splitListOperationNonIT(Message<List<OperationNonITDTO>> messageList) { + if (messageList == null) return List.of(); + + return messageList.getPayload().stream() + .map((OperationNonITDTO operationNonITDTO) -> { + var headers = new HashMap<String, Object>(); + headers.put(Constants.NOM_LOT, operationNonITDTO.getNomLot()); + headers.put(Constants.DATELOT, Objects.toString(operationNonITDTO.getDateLot(), "")); + headers.put(Constants.NOM_ORGANISATION, operationNonITDTO.getNomOrganisation()); + return (Message<OperationNonITDTO>) new GenericMessage<>(operationNonITDTO, headers); + }) + .toList(); + } +} \ No newline at end of file diff --git a/services/api-event-donneesentrees/src/main/resources/application.yaml b/services/api-event-donneesentrees/src/main/resources/application.yaml index ab6e3fc682194d83a75f141313bdea90719e4667..bcf5556dc1a621b047246946b9eebae979248248 100644 --- a/services/api-event-donneesentrees/src/main/resources/application.yaml +++ b/services/api-event-donneesentrees/src/main/resources/application.yaml @@ -29,9 +29,11 @@ numecoeval: partition: "4" entree: equipementPhysique: "entree_equipementPhysique" + operationNonIT: "entree_operationNonIT" messagerie: "entree_messagerie" features: eqp: true + opnit : true mes: true diff --git a/services/api-event-donneesentrees/src/test/java/org/mte/numecoeval/donneesentrees/IntegrationOperationNonITTest.java b/services/api-event-donneesentrees/src/test/java/org/mte/numecoeval/donneesentrees/IntegrationOperationNonITTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c205852688009ef66a5fbe314102f6326d4ef3d7 --- /dev/null +++ b/services/api-event-donneesentrees/src/test/java/org/mte/numecoeval/donneesentrees/IntegrationOperationNonITTest.java @@ -0,0 +1,72 @@ +package org.mte.numecoeval.donneesentrees; + +import io.zonky.test.db.AutoConfigureEmbeddedDatabase; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mte.numecoeval.donneesentrees.test.jdbc.ScriptUtils; +import org.mte.numecoeval.donneesentrees.test.kafka.KafkaConsumerOperationNonIT; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.kafka.test.context.EmbeddedKafka; +import org.springframework.test.context.ActiveProfiles; + +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import static org.awaitility.Awaitility.await; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@ActiveProfiles(profiles = {"test"}) +@AutoConfigureEmbeddedDatabase +@EmbeddedKafka( + bootstrapServersProperty = "spring.kafka.bootstrap-servers", + partitions = 1 +) +class IntegrationOperationNonITTest { + + @Autowired + JdbcTemplate jdbcTemplate; + + @Autowired + KafkaConsumerOperationNonIT kafkaConsumer; + + @BeforeEach + void setup() { + ScriptUtils.loadScript(jdbcTemplate.getDataSource(), "sql/schema.sql"); + jdbcTemplate.batchUpdate("DELETE FROM en_operation_non_it"); + } + + @Test + void whenDataAvailable_shouldUpdateStatusAndSendMessage() { + ScriptUtils.loadScript(jdbcTemplate.getDataSource(), "sql/operation_non_it.sql"); + + // Given + var queryResultCountEntrees = jdbcTemplate.query( + "SELECT count(*) as nbr from en_operation_non_it", + (rs, rowNum) -> rs.getInt("nbr") + ); + var nbrEntrees = queryResultCountEntrees.get(0); + + // When + jdbcTemplate.batchUpdate("UPDATE en_operation_non_it SET statut_traitement = 'A_INGERER'"); + + // Then + Assertions.assertEquals(1, nbrEntrees); + await().atMost(10, TimeUnit.SECONDS) + .until(() -> { + var queryResultCountEntreesIngerees = jdbcTemplate.query( + "SELECT count(*) as nbr from en_operation_non_it WHERE statut_traitement = 'INGERE'", + (rs, rowNum) -> rs.getInt("nbr") + ); + + return !queryResultCountEntreesIngerees.isEmpty() && Objects.equals(nbrEntrees, queryResultCountEntreesIngerees.get(0)); + }); + + await().atMost(5, TimeUnit.SECONDS) + .until(() -> nbrEntrees == kafkaConsumer.getPayloads().size()); + + } + +} diff --git a/services/api-event-donneesentrees/src/test/java/org/mte/numecoeval/donneesentrees/test/kafka/KafkaConsumerConfig.java b/services/api-event-donneesentrees/src/test/java/org/mte/numecoeval/donneesentrees/test/kafka/KafkaConsumerConfig.java index 546cbec0223a5a5c62ec1b94a51879121a184904..a2a80eb2a1e40c571854836a96ed755520cac911 100644 --- a/services/api-event-donneesentrees/src/test/java/org/mte/numecoeval/donneesentrees/test/kafka/KafkaConsumerConfig.java +++ b/services/api-event-donneesentrees/src/test/java/org/mte/numecoeval/donneesentrees/test/kafka/KafkaConsumerConfig.java @@ -2,6 +2,7 @@ package org.mte.numecoeval.donneesentrees.test.kafka; import org.mte.numecoeval.topic.data.EquipementPhysiqueDTO; import org.mte.numecoeval.topic.data.MessagerieDTO; +import org.mte.numecoeval.topic.data.OperationNonITDTO; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.kafka.annotation.EnableKafka; @@ -24,6 +25,18 @@ public class KafkaConsumerConfig { return new KafkaConsumerEquipementPhysique(); } + @Bean + public ConcurrentKafkaListenerContainerFactory<String, OperationNonITDTO> kafkaListenerContainerFactoryOperationNonIT(ConsumerFactory<String, OperationNonITDTO> consumerFactory) { + ConcurrentKafkaListenerContainerFactory<String, OperationNonITDTO> factory = new ConcurrentKafkaListenerContainerFactory<>(); + factory.setConsumerFactory(consumerFactory); + return factory; + } + + @Bean + public KafkaConsumer<OperationNonITDTO> kafkaConsumerOperationNonIT() { + return new KafkaConsumerOperationNonIT(); + } + @Bean public ConcurrentKafkaListenerContainerFactory<String, MessagerieDTO> kafkaListenerContainerFactoryMessagerie(ConsumerFactory<String, MessagerieDTO> consumerFactory) { ConcurrentKafkaListenerContainerFactory<String, MessagerieDTO> factory = new ConcurrentKafkaListenerContainerFactory<>(); diff --git a/services/api-event-donneesentrees/src/test/java/org/mte/numecoeval/donneesentrees/test/kafka/KafkaConsumerOperationNonIT.java b/services/api-event-donneesentrees/src/test/java/org/mte/numecoeval/donneesentrees/test/kafka/KafkaConsumerOperationNonIT.java new file mode 100644 index 0000000000000000000000000000000000000000..fec39b94201e25c896b7a62168b7d5e8ad02bcca --- /dev/null +++ b/services/api-event-donneesentrees/src/test/java/org/mte/numecoeval/donneesentrees/test/kafka/KafkaConsumerOperationNonIT.java @@ -0,0 +1,17 @@ +package org.mte.numecoeval.donneesentrees.test.kafka; + +import lombok.extern.slf4j.Slf4j; +import org.mte.numecoeval.topic.data.OperationNonITDTO; +import org.springframework.kafka.annotation.KafkaListener; + +@Slf4j +public class KafkaConsumerOperationNonIT extends KafkaConsumer<OperationNonITDTO> { + + @Override + @KafkaListener(topics = "${numecoeval.topic.entree.operationNonIT}") + public void consumeMessage(OperationNonITDTO message) { + log.info("############# Playload = {}", message); + payloads.add(message); + latch.countDown(); + } +} diff --git a/services/api-event-donneesentrees/src/test/resources/sql/equipment_physique.sql b/services/api-event-donneesentrees/src/test/resources/sql/equipment_physique.sql index 4d532f98f7ad3b40923028332393225f3bec6522..8340ef882de7ec7a6990c4dc684e01f1ff63cc75 100644 --- a/services/api-event-donneesentrees/src/test/resources/sql/equipment_physique.sql +++ b/services/api-event-donneesentrees/src/test/resources/sql/equipment_physique.sql @@ -4,11 +4,11 @@ VALUES (6002, '2023-03-08 19:45:39.484539', 'ENTITE|2022-01-01', '2022-01-01', ' 'EN_ATTENTE', NULL, 'SOURCE_A'); INSERT INTO en_equipement_physique (id, date_creation, nom_lot, date_lot, nom_organisation, conso_elec_annuelle, - date_achat, date_retrait, duree_vie_defaut, go_telecharge, modele, nb_coeur, mode_utilisation, taux_utilisation, + date_achat, date_retrait, duree_vie_defaut, duree_usage_interne, duree_usage_amont, duree_usage_aval, go_telecharge, modele, nb_coeur, mode_utilisation, taux_utilisation, nb_jour_utilise_an, nom_court_datacenter, nom_entite, nom_equipement_physique, pays_utilisation, quantite, serveur, statut, "type", - utilisateur, statut_traitement, date_update, nom_source_donnee) -VALUES (376826, '2023-03-23 15:53:51.179031', 'ENTITE|2022-01-01', '2022-01-01', 'ENTITE', NULL, '2022-01-01', NULL, 8.0, 0.0, + utilisateur, statut_traitement, date_update, nom_source_donnee, qualite) +VALUES (376826, '2023-03-23 15:53:51.179031', 'ENTITE|2022-01-01', '2022-01-01', 'ENTITE', NULL, '2022-01-01', NULL, 8.0, 5.0, 1.0, 2.0, 0.0, 'computer monitor-01-55', '','BYOD',0.4, 365.0, '', 'ENTITE', '2023-03-09-Ecran-105', 'France', 13.0, false, 'actif', 'Ecran', - '', 'EN_ATTENTE', NULL, 'SOURCE_A'); + '', 'EN_ATTENTE', NULL, 'SOURCE_A','HAUTE'); diff --git a/services/api-event-donneesentrees/src/test/resources/sql/operation_non_it.sql b/services/api-event-donneesentrees/src/test/resources/sql/operation_non_it.sql new file mode 100644 index 0000000000000000000000000000000000000000..f4da7a7a90271594a651651ed1b30e0115151154 --- /dev/null +++ b/services/api-event-donneesentrees/src/test/resources/sql/operation_non_it.sql @@ -0,0 +1,4 @@ +INSERT INTO en_operation_non_it (id, date_creation, nom_lot, date_lot, nom_organisation,nom_item_non_it, quantite, type, +duree_de_vie, localisation, nom_entite,nom_source_donnee,nom_court_datacenter,description,conso_elec_annuelle,statut_traitement,date_update,qualite) +VALUES (11002, '2023-03-23 15:53:37.073851', 'nomlot', '2022-01-01', 'nomOrga', 'nomitem', 32, 'type', 31, + 'Localisation', 'Entite', 'Source','nomCourtDatacenter','description',100,'EN_ATTENTE',NULL,'HAUTE'); diff --git a/services/api-event-donneesentrees/src/test/resources/sql/schema.sql b/services/api-event-donneesentrees/src/test/resources/sql/schema.sql index 32f7442baecbd02dcd6d646bf55c533a63c0c0e3..02c3eb7151d756b3d0a455b48062e37094a961bc 100644 --- a/services/api-event-donneesentrees/src/test/resources/sql/schema.sql +++ b/services/api-event-donneesentrees/src/test/resources/sql/schema.sql @@ -28,6 +28,7 @@ CREATE TABLE IF NOT EXISTS en_data_center nom_entite varchar(255) NULL, nom_long_datacenter varchar(255) NULL, pue float8 NULL, + qualite varchar(255) NULL, CONSTRAINT en_data_center_pkey PRIMARY KEY (id) ); @@ -44,6 +45,9 @@ CREATE TABLE IF NOT EXISTS en_equipement_physique date_achat date NULL, date_retrait date NULL, duree_vie_defaut float8 NULL, + duree_usage_interne float8 NULL, + duree_usage_amont float8 NULL, + duree_usage_aval float8 NULL, go_telecharge float4 NULL, modele varchar(255) NULL, nb_coeur varchar(255) NULL, @@ -59,6 +63,7 @@ CREATE TABLE IF NOT EXISTS en_equipement_physique taux_utilisation float8 NULL, "type" varchar(255) NULL, utilisateur varchar(255) NULL, + qualite varchar(255) NULL, CONSTRAINT en_equipement_physique_pkey PRIMARY KEY (id) ); @@ -75,27 +80,51 @@ CREATE TABLE IF NOT EXISTS en_equipement_virtuel nom_equipement_physique varchar(255) NULL, nom_equipement_virtuel varchar(255) NULL, vcpu int4 NULL, + qualite varchar(255) NULL, CONSTRAINT en_equipement_virtuel_pkey PRIMARY KEY (id) ); CREATE TABLE IF NOT EXISTS en_application ( - id int8 NOT NULL, - date_creation timestamp NULL, - date_lot date NULL, - nom_lot varchar(255) NULL, - nom_organisation varchar(255) NULL, - nom_source_donnee varchar(255) NULL, - domaine varchar(255) NULL, - nom_application varchar(255) NULL, - nom_entite varchar(255) NULL, - nom_equipement_virtuel varchar(255) NULL, - nom_equipement_physique varchar(255) NULL, - sous_domaine varchar(255) NULL, - type_environnement varchar(255) NULL, + id int8 NOT NULL, + date_creation timestamp NULL, + date_lot date NULL, + nom_lot varchar(255) NULL, + nom_organisation varchar(255) NULL, + nom_source_donnee varchar(255) NULL, + domaine varchar(255) NULL, + nom_application varchar(255) NULL, + nom_entite varchar(255) NULL, + nom_equipement_virtuel varchar(255) NULL, + nom_equipement_physique varchar(255) NULL, + sous_domaine varchar(255) NULL, + type_environnement varchar(255) NULL, + qualite varchar(255) NULL, CONSTRAINT en_application_pkey PRIMARY KEY (id) ); +CREATE TABLE IF NOT EXISTS en_operation_non_it +( + id int8 NOT NULL, + date_creation timestamp NULL, + date_update timestamp NULL, + date_lot date NULL, + nom_lot varchar(255) NULL, + nom_organisation varchar(255) NULL, + nom_source_donnee varchar(255) NULL, + nom_item_non_it varchar(255) NULL, + quantite float8 NULL, + type varchar(255) NULL, + duree_de_vie float8 NULL, + localisation varchar(255) NULL, + nom_entite varchar(255) NULL, + nom_court_datacenter varchar(255) NULL, + description varchar(255) NULL, + conso_elec_annuelle float8 NULL, + statut_traitement varchar(255) NULL, + qualite varchar(255) NULL, + CONSTRAINT en_operation_non_it_pkey PRIMARY KEY (id) +); CREATE TABLE IF NOT EXISTS en_entite ( @@ -136,3 +165,9 @@ ALTER TABLE IF EXISTS en_equipement_physique ADD COLUMN IF NOT EXISTS statut_tra ALTER TABLE IF EXISTS en_equipement_virtuel ADD COLUMN IF NOT EXISTS statut_traitement varchar(255); ALTER TABLE IF EXISTS en_application ADD COLUMN IF NOT EXISTS statut_traitement varchar(255); ALTER TABLE IF EXISTS en_messagerie ADD COLUMN IF NOT EXISTS statut_traitement varchar(255); + +ALTER TABLE IF EXISTS en_equipement_physique ADD COLUMN IF NOT EXISTS qualite varchar(255); +ALTER TABLE IF EXISTS en_application ADD COLUMN IF NOT EXISTS qualite varchar(255); +ALTER TABLE IF EXISTS en_operation_non_it ADD COLUMN IF NOT EXISTS qualite varchar(255); +ALTER TABLE IF EXISTS en_equipement_virtuel ADD COLUMN IF NOT EXISTS qualite varchar(255); +ALTER TABLE IF EXISTS en_data_center ADD COLUMN IF NOT EXISTS qualite varchar(255); \ No newline at end of file diff --git a/services/api-expositiondonneesentrees/pom.xml b/services/api-expositiondonneesentrees/pom.xml index 348593d935d923a8fbe3544c95094d3414ec5480..4fae7f992987d13f36dd320479c66aaa33b22135 100644 --- a/services/api-expositiondonneesentrees/pom.xml +++ b/services/api-expositiondonneesentrees/pom.xml @@ -5,11 +5,11 @@ <parent> <groupId>org.mte.numecoeval</groupId> <artifactId>core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <artifactId>api-expositiondonneesentrees</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> <name>api-expositiondonneesentrees</name> <description>API Exposition des données d'entrées - Exposition par API pour injecter des données d'entrées </description> diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/Application.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/Application.java index cc7bb1c31c5eab2406a7590da3a467275cd4af73..fed992c5d539ed37445957048bb32a92d34d97eb 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/Application.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/Application.java @@ -22,4 +22,5 @@ public class Application extends AbstractEntree { String sousDomaine; String nomEntite; String nomEquipementPhysique; + String qualite; } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/DataCenter.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/DataCenter.java index cc5a9929178546d03ed5d350bf50e87d505ded73..a533289ddfb49a9cf471a716f69ddd9d14c8e487 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/DataCenter.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/DataCenter.java @@ -20,5 +20,5 @@ public class DataCenter extends AbstractEntree { Double pue; String localisation; String nomEntite; - + String qualite; } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/DonneesEntree.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/DonneesEntree.java index b1fc6b302b4d2be80a4559bd0927dd71e7df6e77..ddfeaa4281d4d55dea460ba4d575ae876c5fc2b2 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/DonneesEntree.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/DonneesEntree.java @@ -27,4 +27,7 @@ public class DonneesEntree extends AbstractEntree { List<Entite> entites = new ArrayList<>(); + List<OperationNonIT> operationsNonIT = new ArrayList<>(); + + String dureeUsage; } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/EquipementPhysique.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/EquipementPhysique.java index cab21accd9f24190b11765b2b48c839f6798f9f2..784dcb39abd443f6139449637fd6c9956a511687 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/EquipementPhysique.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/EquipementPhysique.java @@ -24,6 +24,9 @@ public class EquipementPhysique extends AbstractEntree { String utilisateur; LocalDate dateAchat; LocalDate dateRetrait; + Double dureeUsageInterne; + Double dureeUsageAmont; + Double dureeUsageAval; String nbCoeur; String nomCourtDatacenter; Double nbJourUtiliseAn; @@ -34,4 +37,5 @@ public class EquipementPhysique extends AbstractEntree { Double quantite; String modeUtilisation; Double tauxUtilisation; + String qualite; } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/EquipementVirtuel.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/EquipementVirtuel.java index e93006d002a0d5c1f7cd6c6ca1d95a24cfef98ff..05adcde9d75afd98e8d0a99f32a5d39d90d14693 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/EquipementVirtuel.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/EquipementVirtuel.java @@ -24,4 +24,5 @@ public class EquipementVirtuel extends AbstractEntree { String typeEqv; Double capaciteStockage; Double cleRepartition; + String qualite; } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/OperationNonIT.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/OperationNonIT.java new file mode 100644 index 0000000000000000000000000000000000000000..aaf89e264c444cb92fe2edb811a104c9381afc02 --- /dev/null +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/OperationNonIT.java @@ -0,0 +1,27 @@ +package org.mte.numecoeval.expositiondonneesentrees.domain.model; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.Accessors; +import lombok.experimental.SuperBuilder; + +@Getter +@Setter +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +@SuperBuilder +@Accessors(chain = true) +public class OperationNonIT extends AbstractEntree { + String nomItemNonIT; + Double quantite; + String type; + Double dureeDeVie; + String localisation; + String nomEntite; + String nomCourtDatacenter; + String description; + Double consoElecAnnuelle; + String qualite; +} diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/RapportDemandeCalcul.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/RapportDemandeCalcul.java index 34dcdd17e3e5ff51a5b6822f4627ea18d2b1b324..1ca589b138af5c09f01790caef3cb047f86c15a6 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/RapportDemandeCalcul.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/model/RapportDemandeCalcul.java @@ -21,5 +21,6 @@ public class RapportDemandeCalcul { Integer nbrEquipementPhysique; Integer nbrEquipementVirtuel; Integer nbrApplication; + Integer nbrOperationNonIT; Integer nbrMessagerie; } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/input/ImportDonneesEntreePort.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/input/ImportDonneesEntreePort.java index 60aad67f37ea07507fcf10029e705b2ce1035d92..b53d99b3bc43bd40cbc8d585f767f0d952ea3c41 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/input/ImportDonneesEntreePort.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/input/ImportDonneesEntreePort.java @@ -1,28 +1,32 @@ package org.mte.numecoeval.expositiondonneesentrees.domain.ports.input; import org.apache.commons.csv.CSVRecord; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; +import org.mte.numecoeval.expositiondonneesentrees.domain.exception.ValidationException; import org.mte.numecoeval.expositiondonneesentrees.domain.model.*; import org.springframework.web.multipart.MultipartFile; import java.time.LocalDate; +import java.util.Arrays; import java.util.List; @SuppressWarnings("java:S107") // Obligatoire à cause de la gestion des fichiers différents au niveau contrat d'interface public interface ImportDonneesEntreePort { - String EQUIPEMENT_PHYSIQUE_CSV_HEADER = "modele;quantite;nomEquipementPhysique;type;statut;paysDUtilisation;utilisateur;dateAchat;dateRetrait;nbCoeur;nomCourtDatacenter;goTelecharge;nbJourUtiliseAn;consoElecAnnuelle"; + String EQUIPEMENT_PHYSIQUE_CSV_HEADER = "modele;quantite;nomEquipementPhysique;type;statut;paysDUtilisation;utilisateur;nbCoeur;nomCourtDatacenter;goTelecharge;nbJourUtiliseAn;consoElecAnnuelle"; String CSV_SEPARATOR = ";"; String DATA_CENTER_CSV_HEADER = "nomCourtDatacenter;nomLongDatacenter;pue;localisation"; - String EQUIPEMENT_VIRTUEL_CSV_HEADER = "nomEquipementPhysique;vCPU;cluster"; - String APPLICATION_CSV_HEADER = "nomApplication;typeEnvironnement;nomEquipementPhysique;domaine;sousDomaine"; + String OPERATION_NON_IT_CSV_HEADER = "nomItemNonIT;quantite;type;localisation;dureeDeVie;nomCourtDatacenter;description;consoElecAnnuelle"; + String[] OPERATION_NON_IT_NOT_BLANK_FIELDS = {"nomItemNonIT", "quantite", "type", "localisation"}; String MESSAGERIE_CSV_HEADER = "nombreMailEmis;nombreMailEmisXDestinataires;volumeTotalMailEmis;MoisAnnee"; String ENTITE_CSV_HEADER = "nomEntite;nbCollaborateurs;responsableEntite;responsableNumeriqueDurable"; + String MESSAGE_LIGNE_INVALIDE = "La ligne n°%d est invalide : %s"; ResultatImport importCsv(String nomOrganisation, String nomLot, String dateLot, MultipartFile csvDataCenter, MultipartFile csvEquipementPhysique, MultipartFile csvEquipementVirtuel, - MultipartFile csvApplication, MultipartFile csvMessagerie, MultipartFile csvEntite); + MultipartFile csvApplication, MultipartFile csvOperationNonIT, MultipartFile csvMessagerie, MultipartFile csvEntite); Pair<RapportImport, List<DataCenter>> importDataCenter(String nomLot, LocalDate dateLot, String nomOrganisation, MultipartFile csvDataCenter); @@ -32,10 +36,13 @@ public interface ImportDonneesEntreePort { Pair<RapportImport, List<Application>> importApplications(String nomLot, LocalDate dateLot, String nomOrganisation, MultipartFile csvApplication); + Pair<RapportImport, List<OperationNonIT>> importOperationsNonIT(String nomLot, LocalDate dateLot, String nomOrganisation, MultipartFile csvOperationNonIT); + Pair<RapportImport, List<Messagerie>> importMessageries(String nomLot, LocalDate dateLot, String nomOrganisation, MultipartFile csvMessagerie); Pair<RapportImport, List<Entite>> importEntite(String nomLot, LocalDate dateLot, String nomOrganisation, MultipartFile csvMessagerie); + default boolean isFieldIsMappedAtLeastOnce(CSVRecord csvRecord, String mainName, String... alternativeNames) { if (csvRecord.isMapped(mainName)) { return true; @@ -48,4 +55,30 @@ public interface ImportDonneesEntreePort { } return false; } + + default String checkAllHeadersAreMapped(CSVRecord csvRecord, String[] headers) { + if (Arrays.stream(headers).allMatch(csvRecord::isMapped)) { + return null; + } + return (MESSAGE_LIGNE_INVALIDE.formatted(csvRecord.getRecordNumber() + 1, "Entêtes incohérentes")); + } + + default String checkFieldsAreMappedAndNotBlankInCSVRecord(CSVRecord csvRecord, String[] fields) throws ValidationException { + for (String field : fields) { + if (StringUtils.isBlank(csvRecord.get(field))) { + return (MESSAGE_LIGNE_INVALIDE.formatted(csvRecord.getRecordNumber() + 1, "La colonne " + field + " ne peut être vide")); + } + } + return null; + } + + default String checkCSVRecord(CSVRecord csvRecord, String[] mandatoryHeaders, String[] notBlankFields) { + if (checkAllHeadersAreMapped(csvRecord, mandatoryHeaders) != null) { + return checkAllHeadersAreMapped(csvRecord, mandatoryHeaders); + } else if (checkFieldsAreMappedAndNotBlankInCSVRecord(csvRecord, notBlankFields) != null) { + return checkFieldsAreMappedAndNotBlankInCSVRecord(csvRecord, notBlankFields); + } + return null; + } + } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/input/impl/ImportDonneesEntreePortImpl.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/input/impl/ImportDonneesEntreePortImpl.java index 2b1557429d22610d08bbe2389ff8ebec0ddb5a4c..cdb09811ef29d757887f67ef4b1435b06f757a4f 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/input/impl/ImportDonneesEntreePortImpl.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/input/impl/ImportDonneesEntreePortImpl.java @@ -10,11 +10,12 @@ import org.mte.numecoeval.expositiondonneesentrees.domain.ports.input.ImportDonn import org.mte.numecoeval.expositiondonneesentrees.domain.ports.output.ReferentielServicePort; import org.mte.numecoeval.expositiondonneesentrees.generated.api.model.StatutTraitement; import org.mte.numecoeval.expositiondonneesentrees.infrastructure.helper.CSVHelper; +import org.mte.numecoeval.expositiondonneesentrees.infrastructure.service.DefaultValueService; import org.mte.numecoeval.expositiondonneesentrees.infrastructure.service.ErrorManagementService; import org.mte.numecoeval.expositiondonneesentrees.referentiels.generated.api.model.TypeEquipementDTO; +import org.mte.numecoeval.expositiondonneesentrees.referentiels.generated.api.model.TypeItemDTO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Value; import org.springframework.web.multipart.MultipartFile; import java.io.FileNotFoundException; @@ -29,21 +30,18 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { private static final String LABEL_NOM_EQUIPEMENT_PHYSIQUE = "nomEquipementPhysique"; private static final String LABEL_NOM_VM = "nomVM"; private static final String LABEL_NOM_EQUIPEMENT_VIRTUEL = "nomEquipementVirtuel"; + private static final String LABEL_nom_item_non_it = "nomItemNonIT"; private static final String[] EQUIPEMENT_PHYSIQUE_HEADER = EQUIPEMENT_PHYSIQUE_CSV_HEADER.split(CSV_SEPARATOR); - private static final String[] DATA_CENTER_HEADER = DATA_CENTER_CSV_HEADER.split(CSV_SEPARATOR); - private static final String[] EQUIPEMENT_VIRTUEL_HEADER = EQUIPEMENT_VIRTUEL_CSV_HEADER.split(CSV_SEPARATOR); - private static final String[] APPLICATION_HEADER = APPLICATION_CSV_HEADER.split(CSV_SEPARATOR); private static final String[] MESSAGERIE_HEADER = MESSAGERIE_CSV_HEADER.split(CSV_SEPARATOR); private static final String[] ENTITE_HEADER = ENTITE_CSV_HEADER.split(CSV_SEPARATOR); + private static final String[] OPERATION_NON_IT_HEADER = OPERATION_NON_IT_CSV_HEADER.split(CSV_SEPARATOR); private static final String HEADER_NOM_ENTITE = "nomEntite"; private static final String HEADER_NOM_SOURCE_DONNEE = "nomSourceDonnee"; private static final String LIGNE_INCONSISTENTE = "LIGNE_INCONSISTENTE"; - - private static final Logger LOGGER = LoggerFactory.getLogger(ImportDonneesEntreePortImpl.class); private static final String STATUT_TRAITEMENT_EN_ATTENTE = StatutTraitement.EN_ATTENTE.getValue(); @@ -51,10 +49,9 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { final ErrorManagementService errorManagementService; - final Map<String, String> errorMessages; + final DefaultValueService defaultValueService; - @Value("#{'${constraints.mode-utilisation}'.split(',')}") - private List<String> modeUtilisationList; + final Map<String, String> errorMessages; @Override public ResultatImport importCsv(String nomOrganisation, String nomLot, String dateLot, @@ -62,6 +59,7 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { MultipartFile csvEquipementPhysique, MultipartFile csvEquipementVirtuel, MultipartFile csvApplication, + MultipartFile csvOperationNonIT, MultipartFile csvMessagerie, MultipartFile csvEntite ) { @@ -96,7 +94,11 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { resultatImport.getRapports().add(importApplications.getKey()); resultatImport.getDonneesEntree().getApplications().addAll(importApplications.getValue()); } - + if (csvOperationNonIT != null) { + Pair<RapportImport, List<OperationNonIT>> importOperationsNonIT = importOperationsNonIT(nomLot, dateLotAsDate, nomOrganisation, csvOperationNonIT); + resultatImport.getRapports().add(importOperationsNonIT.getKey()); + resultatImport.getDonneesEntree().setOperationsNonIT(importOperationsNonIT.getValue()); + } if (csvMessagerie != null) { Pair<RapportImport, List<Messagerie>> importMessagerie = importMessageries(nomLot, dateLotAsDate, nomOrganisation, csvMessagerie); resultatImport.getRapports().add(importMessagerie.getKey()); @@ -108,6 +110,7 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { resultatImport.getRapports().add(importEntites.getKey()); resultatImport.getDonneesEntree().setEntites(importEntites.getValue()); } + return resultatImport; } @@ -132,22 +135,33 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { } else { String localisation = CSVHelper.safeString(csvRecord, "localisation"); String nomLongDataCenter = CSVHelper.safeString(csvRecord, "nomLongDatacenter"); + String nomCourtDataCenter = CSVHelper.safeString(csvRecord, "nomCourtDatacenter"); + + String qualite = CSVHelper.safeString(csvRecord, "qualite"); + if (qualite != null) qualite = qualite.toUpperCase(); + + String checkQualite = errorManagementService.checkQualiteDonnees(qualite, "Le datacenter", nomCourtDataCenter); + if (checkQualite != null) { + qualite = null; + rapportImport.getAvertissements().add(checkQualite); + } + var dataCenter = DataCenter.builder() .statutTraitement(STATUT_TRAITEMENT_EN_ATTENTE) .nomLot(nomLot) .dateLot(dateLot) .nomOrganisation(nomOrganisation) - .nomCourtDatacenter(CSVHelper.safeString(csvRecord, "nomCourtDatacenter")) + .nomCourtDatacenter(nomCourtDataCenter) .nomLongDatacenter(nomLongDataCenter) .pue(CSVHelper.safeDouble(csvRecord, "pue")) .localisation(localisation) .nomEntite(CSVHelper.safeString(csvRecord, HEADER_NOM_ENTITE)) .nomSourceDonnee(CSVHelper.safeString(csvRecord, HEADER_NOM_SOURCE_DONNEE)) + .qualite(qualite) .build(); domainModels.add(dataCenter); rapportImport.getErreurs().addAll(errorManagementService.checkDataCenter(dataCenter)); - } }); @@ -169,7 +183,6 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { } rapportImport.setNbrLignesImportees(domainModels.size()); - return Pair.of(rapportImport, domainModels); } @@ -190,29 +203,42 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { .setTrim(true) .setSkipHeaderRecord(true) .build().parse(reader); + records.forEach(csvRecord -> { + String nomEquipementPhysique = CSVHelper.safeString(csvRecord, LABEL_NOM_EQUIPEMENT_PHYSIQUE, "equipement"); String typeEquipement = csvRecord.get("type"); + String checkNomTypeItem = errorManagementService.checkNomTypeItem(typeEquipement, "L'équipement physique", nomEquipementPhysique); var refTypeEquipementOpt = typesEquipement.stream() .filter(refType -> refType.getType().equals(typeEquipement)) .findFirst(); if (!Arrays.stream(EQUIPEMENT_PHYSIQUE_HEADER).allMatch(csvRecord::isMapped)) { rapportImport.getErreurs().add(errorMessages.get(LIGNE_INCONSISTENTE).formatted(csvEquipementPhysique.getOriginalFilename(), csvRecord.getRecordNumber() + 1)); + } else if (checkNomTypeItem != null) { + rapportImport.getErreurs().add(checkNomTypeItem); } else if (refTypeEquipementOpt.isEmpty()) { // CA 1.1 - rapportImport.getErreurs().add(errorMessages.get("TYPE_EQUIPEMENT_INCONNU").formatted(csvRecord.get("type"), CSVHelper.safeString(csvRecord, LABEL_NOM_EQUIPEMENT_PHYSIQUE, "equipement"))); + rapportImport.getErreurs().add(errorMessages.get("TYPE_ITEM_INCONNU").formatted(csvRecord.get("type"), CSVHelper.safeString(csvRecord, LABEL_NOM_EQUIPEMENT_PHYSIQUE, "equipement"))); } else { var goTelechargeStr = CSVHelper.safeString(csvRecord, "goTelecharge"); Float goTelecharge = goTelechargeStr == null ? null : NumberUtils.toFloat(goTelechargeStr); + var dureeUsageInterneStr = CSVHelper.safeString(csvRecord, "dureeUsageInterne"); + Double dureeUsageInterne = NumberUtils.isCreatable(dureeUsageInterneStr) ? NumberUtils.toDouble(dureeUsageInterneStr) : null; + var dureeUsageAmontStr = CSVHelper.safeString(csvRecord, "dureeUsageAmont"); + Double dureeUsageAmont = dureeUsageAmontStr == null ? 0 : NumberUtils.toDouble(dureeUsageAmontStr); + var dureeUsageAvalStr = CSVHelper.safeString(csvRecord, "dureeUsageAval"); + Double dureeUsageAval = dureeUsageAvalStr == null ? 0 : NumberUtils.toDouble(dureeUsageAvalStr); var tauxUtilisationStr = CSVHelper.safeString(csvRecord, "tauxUtilisation"); Double tauxUtilisation = NumberUtils.isCreatable(tauxUtilisationStr) ? NumberUtils.toDouble(tauxUtilisationStr) : null; - if (tauxUtilisation != null && (tauxUtilisation < 0 || tauxUtilisation > 1)) { - tauxUtilisation = null; - } - var modeUtilisation = CSVHelper.safeString(csvRecord, "modeUtilisation"); - if (!modeUtilisationList.contains(modeUtilisation)) { - modeUtilisation = null; + + String qualite = CSVHelper.safeString(csvRecord, "qualite"); + if (qualite != null) qualite = qualite.toUpperCase(); + + String checkQualite = errorManagementService.checkQualiteDonnees(qualite, "L'équipement physique", nomEquipementPhysique); + if (checkQualite != null) { + qualite = null; + avertissements.add(checkQualite); } EquipementPhysique equipementToAdd = EquipementPhysique.builder() @@ -221,30 +247,34 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { .dateLot(dateLot) .nomOrganisation(nomOrganisation) .modele(CSVHelper.safeString(csvRecord, "modele", "refEquipement")) - .type(csvRecord.get("type")) + .type(typeEquipement) .quantite(CSVHelper.safeDouble(csvRecord, "quantite")) - .nomEquipementPhysique(CSVHelper.safeString(csvRecord, LABEL_NOM_EQUIPEMENT_PHYSIQUE, "equipement")) + .nomEquipementPhysique(nomEquipementPhysique) .statut(CSVHelper.safeString(csvRecord, "statut")) .paysDUtilisation(CSVHelper.safeString(csvRecord, "paysDUtilisation")) .utilisateur(CSVHelper.safeString(csvRecord, "utilisateur")) .dateAchat(CSVHelper.safeParseLocalDate(csvRecord, "dateAchat")) .dateRetrait(CSVHelper.safeParseLocalDate(csvRecord, "dateRetrait")) + .dureeUsageInterne(dureeUsageInterne) + .dureeUsageAmont(dureeUsageAmont) + .dureeUsageAval(dureeUsageAval) .nbCoeur(CSVHelper.safeString(csvRecord, "nbCoeur")) .nomCourtDatacenter(CSVHelper.safeString(csvRecord, "nomCourtDatacenter", "refDatacenter")) .goTelecharge(goTelecharge) - .modeUtilisation(modeUtilisation) + .modeUtilisation(CSVHelper.safeString(csvRecord, "modeUtilisation")) .tauxUtilisation(tauxUtilisation) .nbJourUtiliseAn(CSVHelper.safeDouble(csvRecord, "nbJourUtiliseAn")) .consoElecAnnuelle(CSVHelper.safeDouble(csvRecord, "consoElecAnnuelle")) .serveur(refTypeEquipementOpt.get().isServeur()) .nomEntite(CSVHelper.safeString(csvRecord, HEADER_NOM_ENTITE)) .nomSourceDonnee(CSVHelper.safeString(csvRecord, HEADER_NOM_SOURCE_DONNEE)) + .qualite(qualite) .build(); var erreurs = errorManagementService.checkEquipementPhysique(equipementToAdd, refTypeEquipementOpt.get().getRefEquipementParDefaut()); rapportImport.getErreurs().addAll(erreurs.getKey()); avertissements.addAll(erreurs.getValue()); - + defaultValueService.setEquipementValeurDefaut(equipementToAdd); domainModels.add(equipementToAdd); } }); @@ -268,7 +298,6 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { rapportImport.setNbrLignesImportees(domainModels.size()); rapportImport.setAvertissements(avertissements.stream().toList()); - return Pair.of(rapportImport, domainModels); } @@ -294,12 +323,22 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { if (!isRecordOK) { rapportImport.getErreurs().add(errorMessages.get(LIGNE_INCONSISTENTE).formatted(csvEquipementVirtuel.getOriginalFilename(), csvRecord.getRecordNumber() + 1)); } else { + String nomEquipementVirtuel = CSVHelper.safeString(csvRecord, LABEL_NOM_EQUIPEMENT_VIRTUEL, LABEL_NOM_VM); + String qualite = CSVHelper.safeString(csvRecord, "qualite"); + if (qualite != null) qualite = qualite.toUpperCase(); + + String checkQualite = errorManagementService.checkQualiteDonnees(qualite, "L'équipement virtuel", nomEquipementVirtuel); + if (checkQualite != null) { + qualite = null; + rapportImport.getAvertissements().add(checkQualite); + } + EquipementVirtuel equipementVirtuel = EquipementVirtuel.builder() .statutTraitement(STATUT_TRAITEMENT_EN_ATTENTE) .nomLot(nomLot) .dateLot(dateLot) .nomOrganisation(nomOrganisation) - .nomEquipementVirtuel(CSVHelper.safeString(csvRecord, LABEL_NOM_EQUIPEMENT_VIRTUEL, LABEL_NOM_VM)) + .nomEquipementVirtuel(nomEquipementVirtuel) .nomEquipementPhysique(CSVHelper.safeString(csvRecord, LABEL_NOM_EQUIPEMENT_PHYSIQUE)) .nomSourceDonneeEquipementPhysique(CSVHelper.safeString(csvRecord, "nomSourceDonneeEquipementPhysique")) .vCPU(CSVHelper.safeInteger(csvRecord, "vCPU")) @@ -310,6 +349,7 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { .cleRepartition(CSVHelper.safeDouble(csvRecord, "cleRepartition")) .nomEntite(CSVHelper.safeString(csvRecord, HEADER_NOM_ENTITE)) .nomSourceDonnee(CSVHelper.safeString(csvRecord, HEADER_NOM_SOURCE_DONNEE)) + .qualite(qualite) .build(); domainModels.add(equipementVirtuel); @@ -334,7 +374,6 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { } rapportImport.setNbrLignesImportees(domainModels.size()); - return Pair.of(rapportImport, domainModels); } @@ -361,12 +400,21 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { if (!isRecordOK) { rapportImport.getErreurs().add(errorMessages.get(LIGNE_INCONSISTENTE).formatted(csvApplication.getOriginalFilename(), csvRecord.getRecordNumber() + 1)); } else { + String nomApplication = CSVHelper.safeString(csvRecord, "nomApplication"); + String qualite = CSVHelper.safeString(csvRecord, "qualite"); + if (qualite != null) qualite = qualite.toUpperCase(); + + String checkQualite = errorManagementService.checkQualiteDonnees(qualite, "L'application", nomApplication); + if (checkQualite != null) { + qualite = null; + rapportImport.getAvertissements().add(checkQualite); + } Application application = Application.builder() .statutTraitement(STATUT_TRAITEMENT_EN_ATTENTE) .nomLot(nomLot) .dateLot(dateLot) .nomOrganisation(nomOrganisation) - .nomApplication(CSVHelper.safeString(csvRecord, "nomApplication")) + .nomApplication(nomApplication) .typeEnvironnement(CSVHelper.safeString(csvRecord, "typeEnvironnement")) .nomEquipementVirtuel(CSVHelper.safeString(csvRecord, LABEL_NOM_EQUIPEMENT_VIRTUEL, LABEL_NOM_VM)) .nomSourceDonneeEquipementVirtuel(CSVHelper.safeString(csvRecord, "nomSourceDonneeEquipementVirtuel")) @@ -375,6 +423,7 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { .nomEntite(CSVHelper.safeString(csvRecord, HEADER_NOM_ENTITE)) .nomEquipementPhysique(CSVHelper.safeString(csvRecord, LABEL_NOM_EQUIPEMENT_PHYSIQUE)) .nomSourceDonnee(CSVHelper.safeString(csvRecord, HEADER_NOM_SOURCE_DONNEE)) + .qualite(qualite) .build(); domainModels.add(application); @@ -399,7 +448,93 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { } rapportImport.setNbrLignesImportees(domainModels.size()); + return Pair.of(rapportImport, domainModels); + } + + @Override + public Pair<RapportImport, List<OperationNonIT>> importOperationsNonIT(String nomLot, LocalDate dateLot, String nomOrganisation, MultipartFile csvOperationNonIT) { + List<OperationNonIT> domainModels = new ArrayList<>(); + RapportImport rapportImport = new RapportImport(); + rapportImport.setFichier(csvOperationNonIT.getOriginalFilename()); + rapportImport.setType("operation_non_it"); + List<TypeItemDTO> typesItem = referentielServicePort.getAllTypesItem(); + + try (Reader reader = new InputStreamReader(csvOperationNonIT.getInputStream())) { + Iterable<CSVRecord> records = CSVFormat.DEFAULT.builder() + .setHeader() + .setAllowMissingColumnNames(true) + .setDelimiter(CSV_SEPARATOR) + .setTrim(true) + .setSkipHeaderRecord(true) + .build().parse(reader); + records.forEach(csvRecord -> + { + String nomItem = CSVHelper.safeString(csvRecord, LABEL_nom_item_non_it); + String typeItem = csvRecord.get("type"); + String checkNomTypeItem = errorManagementService.checkNomTypeItem(typeItem, "L'opération non IT", nomItem); + var refTypeItemOpt = typesItem.stream() + .filter(refType -> refType.getType().equals(typeItem)) + .findFirst(); + String error = checkCSVRecord(csvRecord, OPERATION_NON_IT_HEADER, OPERATION_NON_IT_NOT_BLANK_FIELDS); + if (error != null) { + rapportImport.getErreurs().add(error); + } else if (checkNomTypeItem != null) { + rapportImport.getErreurs().add(checkNomTypeItem); + } else if (refTypeItemOpt.isEmpty()) { + rapportImport.getErreurs().add(errorMessages.get("TYPE_ITEM_INCONNU").formatted(csvRecord.get("type"), nomItem)); + } else { + String qualite = CSVHelper.safeString(csvRecord, "qualite"); + if (qualite != null) qualite = qualite.toUpperCase(); + + String checkQualite = errorManagementService.checkQualiteDonnees(qualite, "L'item", nomItem); + if (checkQualite != null) { + qualite = null; + rapportImport.getAvertissements().add(checkQualite); + } + + OperationNonIT operationToAdd = OperationNonIT.builder() + .statutTraitement(STATUT_TRAITEMENT_EN_ATTENTE) + .nomLot(nomLot) + .dateLot(dateLot) + .nomOrganisation(nomOrganisation) + .nomItemNonIT(nomItem) + .quantite(CSVHelper.safeDouble(csvRecord, "quantite")) + .type(csvRecord.get("type")) + .dureeDeVie(CSVHelper.safeDouble(csvRecord, "dureeDeVie")) + .localisation(CSVHelper.safeString(csvRecord, "localisation")) + .nomEntite(CSVHelper.safeString(csvRecord, HEADER_NOM_ENTITE)) + .nomSourceDonnee(CSVHelper.safeString(csvRecord, HEADER_NOM_SOURCE_DONNEE)) + .nomCourtDatacenter(CSVHelper.safeString(csvRecord, "nomCourtDatacenter", "refDatacenter")) + .description(CSVHelper.safeString(csvRecord, "description")) + .consoElecAnnuelle(CSVHelper.safeDouble(csvRecord, "consoElecAnnuelle")) + .qualite(qualite) + .build(); + + var erreurs = errorManagementService.checkOperationNonIT(operationToAdd, refTypeItemOpt.get().getRefItemParDefaut()); + rapportImport.getErreurs().addAll(erreurs.getKey()); + rapportImport.getAvertissements().addAll(erreurs.getValue()); + + domainModels.add(operationToAdd); + } + }); + + } catch (FileNotFoundException e) { + LOGGER.error("Erreur CSV pour des opérations non IT introuvables", e); + return Pair.of(RapportImport.builder() + .erreurs(Collections.singletonList("Le fichier CSV des opérations non IT n'est pas trouvable.")) + .build() + , Collections.emptyList() + ); + } catch (Exception e) { + LOGGER.error("Erreur durant la lecture d'un CSV pour des opérations non IT", e); + return Pair.of(RapportImport.builder() + .erreurs(Collections.singletonList("Le fichier CSV des opérations non IT n'est pas lisible par le système.")) + .build() + , Collections.emptyList() + ); + } + rapportImport.setNbrLignesImportees(domainModels.size()); return Pair.of(rapportImport, domainModels); } @@ -458,7 +593,6 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { } rapportImport.setNbrLignesImportees(domainModels.size()); - return Pair.of(rapportImport, domainModels); } @@ -515,7 +649,7 @@ public class ImportDonneesEntreePortImpl implements ImportDonneesEntreePort { } rapportImport.setNbrLignesImportees(domainModels.size()); - return Pair.of(rapportImport, domainModels); } } + diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/input/impl/SoumissionCalculSyncPortImpl.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/input/impl/SoumissionCalculSyncPortImpl.java index c0f73260c61dab67adab68286452b6b65abf9af3..0021cf19999bfa4a66a1dfb720dfa8f9c05dac3f 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/input/impl/SoumissionCalculSyncPortImpl.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/input/impl/SoumissionCalculSyncPortImpl.java @@ -10,6 +10,7 @@ import org.mte.numecoeval.expositiondonneesentrees.infrastructure.adapters.Calcu import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.repository.DataCenterRepository; import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.repository.EquipementPhysiqueRepository; import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.repository.MessagerieRepository; +import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.repository.OperationNonITRepository; import org.mte.numecoeval.expositiondonneesentrees.infrastructure.mapper.CalculRestMapper; import org.springframework.stereotype.Service; @@ -21,6 +22,7 @@ import java.util.List; public class SoumissionCalculSyncPortImpl implements SoumissionCalculSyncPort { EquipementPhysiqueRepository equipementPhysiqueRepository; + OperationNonITRepository operationNonITRepository; MessagerieRepository messagerieRepository; DataCenterRepository dataCenterRepository; @@ -34,11 +36,13 @@ public class SoumissionCalculSyncPortImpl implements SoumissionCalculSyncPort { // find equipements physiques à partir de nomLot et nomOrganisation List<Long> equipementPhysiqueIds = equipementPhysiqueRepository.getIdsByNomLotAndStatutTraitement(demandeCalcul.getNomLot(), StatutTraitement.EN_ATTENTE.getValue()); + List<Long> operatioNonITIds = operationNonITRepository.getIdsByNomLotAndStatutTraitement(demandeCalcul.getNomLot(), StatutTraitement.EN_ATTENTE.getValue()); List<Long> messagerieEntityIds = messagerieRepository.getIdsByNomLotAndStatutTraitement(demandeCalcul.getNomLot(), StatutTraitement.EN_ATTENTE.getValue()); // map to Rest var reponseCalculRest = calculsRestClient.postSyncCalcul( equipementPhysiqueIds, + operatioNonITIds, messagerieEntityIds ); diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/input/impl/StatutPourCalculPortImpl.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/input/impl/StatutPourCalculPortImpl.java index 39da64041253166f03d96ff6a093bcfd01f3632d..25106f330713eaeeae3be23629b997477dada3f0 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/input/impl/StatutPourCalculPortImpl.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/input/impl/StatutPourCalculPortImpl.java @@ -28,8 +28,9 @@ public class StatutPourCalculPortImpl implements StatutPourCalculPort { public StatutCalculRest statutDesCalculs(String nomLot, String nomOrganisation) { var volumeEqPh = volumeJdbc.getVolumeBy(nomLot, nomOrganisation, Constants.TABLE_EQUIPEMENT_PHYSIQUE); + var volumeOpNonIT = volumeJdbc.getVolumeBy(nomLot, nomOrganisation, Constants.TABLE_OPERATION_NON_IT); var volumeMessagerie = volumeJdbc.getVolumeBy(nomLot, nomOrganisation, Constants.TABLE_MESSAGERIE); - return statutCalculs(volumeEqPh, volumeMessagerie); + return statutCalculs(volumeEqPh, volumeOpNonIT, volumeMessagerie); } /** @@ -39,9 +40,9 @@ public class StatutPourCalculPortImpl implements StatutPourCalculPort { * @param volumeMessagerie volume de la messagerie * @return le StatutCalculRest */ - public StatutCalculRest statutCalculs(Volume volumeEqPh, Volume volumeMessagerie) { - var totalTraite = volumeEqPh.nbTraite() + volumeMessagerie.nbTraite(); - var totalEnCours = volumeEqPh.nbEnCours() + volumeMessagerie.nbEnCours(); + public StatutCalculRest statutCalculs(Volume volumeEqPh, Volume volumeOpNonIT, Volume volumeMessagerie) { + var totalTraite = volumeEqPh.nbTraite() + volumeOpNonIT.nbTraite() + volumeMessagerie.nbTraite(); + var totalEnCours = volumeEqPh.nbEnCours() + volumeOpNonIT.nbEnCours() + volumeMessagerie.nbEnCours(); if (totalTraite + totalEnCours == 0) { throw new NotFoundException(); @@ -55,6 +56,7 @@ public class StatutPourCalculPortImpl implements StatutPourCalculPort { .statut(statut) .etat(etat + "%") .equipementPhysique(volumeMapper.toRest(volumeEqPh)) + .operationNonIT(volumeMapper.toRest(volumeOpNonIT)) .messagerie(volumeMapper.toRest(volumeMessagerie)) .build(); } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/output/ReferentielServicePort.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/output/ReferentielServicePort.java index 7fc8e1aa6862219b38c93a4915600b5b247f1f54..44eb82e2a01d5c8e8a6a502effe99c5c8c80759b 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/output/ReferentielServicePort.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/domain/ports/output/ReferentielServicePort.java @@ -9,12 +9,15 @@ public interface ReferentielServicePort { List<TypeEquipementDTO> getAllTypesEquipement(); + List<TypeItemDTO> getAllTypesItem(); + CorrespondanceRefEquipementDTO getCorrespondance(String modele); ImpactEquipementDTO getImpactEquipement(String refEquipement, String critere, String etape); + FacteurCaracterisationDTO getFacteurCaracterisation(String critere, String etape, String refItem); + List<EtapeDTO> getAllEtapes(); List<CritereDTO> getAllCriteres(); - } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/adapters/CalculsRestClient.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/adapters/CalculsRestClient.java index c1da6ce1ab509d8143dc84f5bd172c9bd805ffed..096e4d951157bbe02ec5791c9e0b18b2aa92962e 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/adapters/CalculsRestClient.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/adapters/CalculsRestClient.java @@ -3,7 +3,7 @@ package org.mte.numecoeval.expositiondonneesentrees.infrastructure.adapters; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.mte.numecoeval.expositiondonneesentrees.domain.exception.RestException; -import org.mte.numecoeval.expositiondonneesentrees.sync.calculs.generated.api.client.CalculsEquipementPhysiqueEtMessagerieApi; +import org.mte.numecoeval.expositiondonneesentrees.sync.calculs.generated.api.client.CalculsEquipementPhysiqueEtOperationNonItEtMessagerieApi; import org.mte.numecoeval.expositiondonneesentrees.sync.calculs.generated.api.model.ReponseCalculRest; import org.mte.numecoeval.expositiondonneesentrees.sync.calculs.generated.api.model.SyncCalculRest; import org.springframework.stereotype.Service; @@ -16,16 +16,17 @@ import java.util.List; @AllArgsConstructor public class CalculsRestClient { - private CalculsEquipementPhysiqueEtMessagerieApi calculsEquipementPhysiqueEtMessagerieApi; + private CalculsEquipementPhysiqueEtOperationNonItEtMessagerieApi calculsEquipementPhysiqueEtOperationNonItEtMessagerieApi; - public ReponseCalculRest postSyncCalcul(List<Long> equipementPhysiqueIds, List<Long> messagerieIds) { + public ReponseCalculRest postSyncCalcul(List<Long> equipementPhysiqueIds, List<Long> operationNonITIds, List<Long> messagerieIds) { try { var syncCalculRest = new SyncCalculRest(); syncCalculRest.setEquipementPhysiqueIds(equipementPhysiqueIds); + syncCalculRest.setOperationNonITIds(operationNonITIds); syncCalculRest.setMessagerieIds(messagerieIds); - return calculsEquipementPhysiqueEtMessagerieApi.syncCalculByIds(syncCalculRest).block(); + return calculsEquipementPhysiqueEtOperationNonItEtMessagerieApi.syncCalculByIds(syncCalculRest).block(); } catch (WebClientResponseException e) { throw new RestException(e); diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/adapters/ReferentielRestClient.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/adapters/ReferentielRestClient.java index b101173d9df087ab528b0bed0f0ee5be549a3d12..277f1e5da336ffafe3c7e5e7cd991f9f61d51e90 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/adapters/ReferentielRestClient.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/adapters/ReferentielRestClient.java @@ -41,6 +41,12 @@ public class ReferentielRestClient implements ReferentielServicePort { return result.getBody(); } + @Override + public List<TypeItemDTO> getAllTypesItem() { + var result = interneNumEcoEvalApi.getAllTypeItemWithHttpInfo().block(); + return result.getBody(); + } + @Cacheable("CorrespondanceRefEquipement") @Override public CorrespondanceRefEquipementDTO getCorrespondance(String modele) { @@ -72,6 +78,24 @@ public class ReferentielRestClient implements ReferentielServicePort { return null; } + @Cacheable("FacteurCaracterisation") + @Override + public FacteurCaracterisationDTO getFacteurCaracterisation(String critere, String etape, String refEquipement) { + + try { + var res = interneNumEcoEvalApi.getFacteurCaracterisation(critere, etape, refEquipement, null, null).blockFirst(); + if (res != null) { + return res; + } + } catch (WebClientResponseException e) { + if (e.getStatusCode() != HttpStatus.NOT_FOUND) { + log.error("Une erreur est survenue lors de l'appel au référentiel facteurcaracterisation", e); + return null; + } + } + return null; + } + @Cacheable("Etapes") @Override public List<EtapeDTO> getAllEtapes() { diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/cache/SchedulerEvictCache.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/cache/SchedulerEvictCache.java index c3c4ffc90bd6c9cc9c5e73b7d029a49df1c84b14..fbcc643b7ea93035124e6e80d5a0a71e21dc1b3a 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/cache/SchedulerEvictCache.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/cache/SchedulerEvictCache.java @@ -17,7 +17,8 @@ public class SchedulerEvictCache { "Etapes", "Criteres", "CorrespondanceRefEquipement", - "ImpactEquipement" + "ImpactEquipement", + "FacteurCaracterisation" }, allEntries = true) @Scheduled(fixedRateString = "${caching.spring.referentiels}") public void emptyCacheReferentiel() { diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/config/ApplicationPortConfig.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/config/ApplicationPortConfig.java index 7a62c6b92eb85a818dda843aadf2fcb05f9e3fb7..33a0df3c8f727603d81f4c95379adbe5f7002dd0 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/config/ApplicationPortConfig.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/config/ApplicationPortConfig.java @@ -4,26 +4,24 @@ import lombok.AllArgsConstructor; import org.mte.numecoeval.expositiondonneesentrees.domain.ports.input.ImportDonneesEntreePort; import org.mte.numecoeval.expositiondonneesentrees.domain.ports.input.impl.ImportDonneesEntreePortImpl; import org.mte.numecoeval.expositiondonneesentrees.domain.ports.output.ReferentielServicePort; +import org.mte.numecoeval.expositiondonneesentrees.infrastructure.service.DefaultValueService; import org.mte.numecoeval.expositiondonneesentrees.infrastructure.service.ErrorManagementService; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; -import java.util.List; - @Configuration @AllArgsConstructor @ComponentScan(basePackages = "org.mte.numecoeval.expositiondonneesentrees.infrastructure.adapters") public class ApplicationPortConfig { private ReferentielServicePort referentielServicePort; - private ErrorManagementService errorManagementService; + private DefaultValueService defaultValueService; private MessageProperties messageProperties; - private List<String> modeUtilisationList; @Bean public ImportDonneesEntreePort importDonneesEntreePort() { - return new ImportDonneesEntreePortImpl(referentielServicePort, errorManagementService, messageProperties.getMessages(), modeUtilisationList); + return new ImportDonneesEntreePortImpl(referentielServicePort, errorManagementService, defaultValueService, messageProperties.getMessages()); } } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/config/CommonIntegrationConfig.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/config/CommonIntegrationConfig.java index 608aefe087afa6b01d150aed4877dbfee666df83..0896ea4ebb222621f473329525a2a459195d25d0 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/config/CommonIntegrationConfig.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/config/CommonIntegrationConfig.java @@ -2,7 +2,7 @@ package org.mte.numecoeval.expositiondonneesentrees.infrastructure.config; import lombok.extern.slf4j.Slf4j; import org.mte.numecoeval.expositiondonneesentrees.referentiels.generated.api.client.InterneNumEcoEvalApi; -import org.mte.numecoeval.expositiondonneesentrees.sync.calculs.generated.api.client.CalculsEquipementPhysiqueEtMessagerieApi; +import org.mte.numecoeval.expositiondonneesentrees.sync.calculs.generated.api.client.CalculsEquipementPhysiqueEtOperationNonItEtMessagerieApi; import org.mte.numecoeval.expositiondonneesentrees.sync.calculs.generated.api.invoker.ApiClient; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -20,8 +20,8 @@ public class CommonIntegrationConfig { String referentielUrl; @Bean - public CalculsEquipementPhysiqueEtMessagerieApi clientAPISyncCalculs() { - CalculsEquipementPhysiqueEtMessagerieApi calculsApi = new CalculsEquipementPhysiqueEtMessagerieApi(); + public CalculsEquipementPhysiqueEtOperationNonItEtMessagerieApi clientAPISyncCalculs() { + CalculsEquipementPhysiqueEtOperationNonItEtMessagerieApi calculsApi = new CalculsEquipementPhysiqueEtOperationNonItEtMessagerieApi(); var apiClient = new ApiClient(WebClient.builder() .baseUrl(calculUrl) .build()); diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/controller/CalculController.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/controller/CalculController.java index 9727613edf8d5d5f6917e951b15272f2b2aa5adc..aea43dca0a4e592315a3650ad316dbcf5c99a91d 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/controller/CalculController.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/controller/CalculController.java @@ -1,30 +1,34 @@ package org.mte.numecoeval.expositiondonneesentrees.infrastructure.controller; -import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.mte.numecoeval.expositiondonneesentrees.domain.ports.input.SoumissionCalculPort; import org.mte.numecoeval.expositiondonneesentrees.domain.ports.input.SoumissionCalculSyncPort; import org.mte.numecoeval.expositiondonneesentrees.domain.ports.input.StatutPourCalculPort; -import org.mte.numecoeval.expositiondonneesentrees.generated.api.model.DemandeCalculRest; -import org.mte.numecoeval.expositiondonneesentrees.generated.api.model.ModeRest; -import org.mte.numecoeval.expositiondonneesentrees.generated.api.model.RapportDemandeCalculRest; -import org.mte.numecoeval.expositiondonneesentrees.generated.api.model.StatutCalculRest; +import org.mte.numecoeval.expositiondonneesentrees.generated.api.model.*; import org.mte.numecoeval.expositiondonneesentrees.generated.api.server.CalculsApi; +import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.repository.DonneesEntreesRepository; import org.mte.numecoeval.expositiondonneesentrees.infrastructure.mapper.CalculRestMapper; +import org.springframework.beans.factory.annotation.Value; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; @RestController -@AllArgsConstructor @Slf4j +@RequiredArgsConstructor public class CalculController implements CalculsApi { - CalculRestMapper calculRestMapper; + @Value("${regle-par-defaut-duree-usage}") + private String defaultDureeUsage; - SoumissionCalculPort soumissionCalculPort; + final CalculRestMapper calculRestMapper; - SoumissionCalculSyncPort soumissionCalculSyncPort; - StatutPourCalculPort statutPourCalculPort; + final SoumissionCalculPort soumissionCalculPort; + + final SoumissionCalculSyncPort soumissionCalculSyncPort; + final StatutPourCalculPort statutPourCalculPort; + + final DonneesEntreesRepository donneesEntreesRepository; @Override public ResponseEntity<StatutCalculRest> statutPourCalcul(String nomLot, String nomOrganisation) { @@ -34,9 +38,16 @@ public class CalculController implements CalculsApi { } @Override - public ResponseEntity<RapportDemandeCalculRest> soumissionPourCalcul(DemandeCalculRest demandeCalculRest, ModeRest mode) { - log.info("Soumission de calcul pour nom_lot: {}, mode: {}", demandeCalculRest.getNomLot(), mode); + public ResponseEntity<RapportDemandeCalculRest> soumissionPourCalcul(DemandeCalculRest demandeCalculRest, DureeUsage dureeUsage, ModeRest mode) { + + var modeDureeUsage = dureeUsage == null ? DureeUsage.fromValue(defaultDureeUsage) : dureeUsage; + if (DureeUsage.REEL != modeDureeUsage) { + modeDureeUsage = DureeUsage.FIXE; + } + + log.info("Soumission de calcul pour nom_lot: {}, dureeUsage: {}, mode: {}", demandeCalculRest.getNomLot(), modeDureeUsage, mode); var demandeCalcul = calculRestMapper.toDomain(demandeCalculRest); + donneesEntreesRepository.updateDonneesEntreesDureeUsage(String.valueOf(modeDureeUsage), demandeCalculRest.getNomLot()); var soumission = ModeRest.ASYNC == mode ? soumissionCalculPort.soumissionCalcul(demandeCalcul) : diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/controller/ImportCSVController.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/controller/ImportCSVController.java index 80a48f93904645008f71660eeeea325f3403da9a..65e5a6372008f64dcbbb42d766a965e8d7f9bdd9 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/controller/ImportCSVController.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/controller/ImportCSVController.java @@ -41,11 +41,11 @@ public class ImportCSVController implements ImportsApi { ErrorManagementPostSaveService errorManagementPostSaveService; @Override - public ResponseEntity<List<RapportImportRest>> importCSV(String nomOrganisation, String nomLot, String dateLot, MultipartFile csvDataCenter, MultipartFile csvEquipementPhysique, MultipartFile csvEquipementVirtuel, MultipartFile csvApplication, MultipartFile csvMessagerie, MultipartFile csvEntite) { - return importInterneCSV(nomOrganisation, nomLot, dateLot, csvDataCenter, csvEquipementPhysique, csvEquipementVirtuel, csvApplication, csvMessagerie, csvEntite); + public ResponseEntity<List<RapportImportRest>> importCSV(String nomOrganisation, String nomLot, String dateLot, MultipartFile csvDataCenter, MultipartFile csvEquipementPhysique, MultipartFile csvEquipementVirtuel, MultipartFile csvApplication, MultipartFile csvOperationNonIT, MultipartFile csvMessagerie, MultipartFile csvEntite) { + return importInterneCSV(nomOrganisation, nomLot, dateLot, csvDataCenter, csvEquipementPhysique, csvEquipementVirtuel, csvApplication, csvOperationNonIT, csvMessagerie, csvEntite); } - public ResponseEntity<List<RapportImportRest>> importInterneCSV(String nomOrganisation, String nomLot, String dateLot, MultipartFile csvDataCenter, MultipartFile csvEquipementPhysique, MultipartFile csvEquipementVirtuel, MultipartFile csvApplication, MultipartFile csvMessagerie, MultipartFile csvEntite) { + public ResponseEntity<List<RapportImportRest>> importInterneCSV(String nomOrganisation, String nomLot, String dateLot, MultipartFile csvDataCenter, MultipartFile csvEquipementPhysique, MultipartFile csvEquipementVirtuel, MultipartFile csvApplication, MultipartFile csvOperationNonIT, MultipartFile csvMessagerie, MultipartFile csvEntite) { return ResponseEntity.ok( importDonneesFromCSV( nomOrganisation, nomLot, dateLot, @@ -53,6 +53,7 @@ public class ImportCSVController implements ImportsApi { csvEquipementPhysique, csvEquipementVirtuel, csvApplication, + csvOperationNonIT, csvMessagerie, csvEntite ) @@ -73,13 +74,14 @@ public class ImportCSVController implements ImportsApi { MultipartFile csvEquipementPhysique, MultipartFile csvEquipementVirtuel, MultipartFile csvApplication, + MultipartFile csvOperationNonIT, MultipartFile csvMessagerie, MultipartFile csvEntite) throws ValidationException { LOGGER.info("Reception de fichiers pour imports de données d'entrées :Nom Organisation : {}, Nom de Lot : {}, Date de lot : {}", nomOrganisation, nomLot, dateLot); - validateRequestParametersForImportCSV(nomOrganisation, nomLot, dateLot, csvDataCenter, csvEquipementPhysique, csvEquipementVirtuel, csvApplication, csvMessagerie, csvEntite); + validateRequestParametersForImportCSV(nomOrganisation, nomLot, dateLot, csvDataCenter, csvEquipementPhysique, csvEquipementVirtuel, csvApplication, csvOperationNonIT, csvMessagerie, csvEntite); - return importAllCsv(nomOrganisation, nomLot, dateLot, csvDataCenter, csvEquipementPhysique, csvEquipementVirtuel, csvApplication, csvMessagerie, csvEntite); + return importAllCsv(nomOrganisation, nomLot, dateLot, csvDataCenter, csvEquipementPhysique, csvEquipementVirtuel, csvApplication, csvOperationNonIT, csvMessagerie, csvEntite); } /** @@ -91,15 +93,17 @@ public class ImportCSVController implements ImportsApi { * @param csvEquipementPhysique Fichier CSV des équipements physiques * @param csvEquipementVirtuel Fichier CSV des équipements virtuels * @param csvApplication Fichier CSV des applications + * @param csvOperationNonIT Fichier CSV des opérations non IT * @param csvMessagerie Fichier CSV de la messagerie * @param csvEntite Fichier CSV des entités * @throws ResponseStatusException avec le statut 400 lorsque les entrées ne sont pas cohérentes. */ - private void validateRequestParametersForImportCSV(String nomOrganisation, String nomLot, String dateLot, MultipartFile csvDataCenter, MultipartFile csvEquipementPhysique, MultipartFile csvEquipementVirtuel, MultipartFile csvApplication, MultipartFile csvMessagerie, MultipartFile csvEntite) { + private void validateRequestParametersForImportCSV(String nomOrganisation, String nomLot, String dateLot, MultipartFile csvDataCenter, MultipartFile csvEquipementPhysique, MultipartFile csvEquipementVirtuel, MultipartFile csvApplication, MultipartFile csvOperationNonIT, MultipartFile csvMessagerie, MultipartFile csvEntite) { if (CSVHelper.fileIsNullOrEmpty(csvDataCenter) && CSVHelper.fileIsNullOrEmpty(csvEquipementPhysique) && CSVHelper.fileIsNullOrEmpty(csvEquipementVirtuel) && CSVHelper.fileIsNullOrEmpty(csvApplication) + && CSVHelper.fileIsNullOrEmpty(csvOperationNonIT) && CSVHelper.fileIsNullOrEmpty(csvMessagerie) && CSVHelper.fileIsNullOrEmpty(csvEntite) ) { @@ -134,6 +138,7 @@ public class ImportCSVController implements ImportsApi { * @param csvEquipementPhysique Fichier CSV des équipements physiques * @param csvEquipementVirtuel Fichier CSV des équipements virtuels * @param csvApplication Fichier CSV des applications + * @param csvOperationNonIT Fichier CSV des opérations non IT * @param csvMessagerie Fichier CSV de la messagerie * @param csvEntite Fichier CSV des entités * @param dateLot Date du lot associée aux fichiers @@ -142,9 +147,9 @@ public class ImportCSVController implements ImportsApi { * @return {@link List} des {@link RapportImportRest} correspondant à l'import * @throws ValidationException en cas d'absence de donner à pousser dans le système. */ - private List<RapportImportRest> importAllCsv(String nomOrganisation, String nomLot, String dateLot, MultipartFile csvDataCenter, MultipartFile csvEquipementPhysique, MultipartFile csvEquipementVirtuel, MultipartFile csvApplication, MultipartFile csvMessagerie, MultipartFile csvEntite) throws ValidationException { + private List<RapportImportRest> importAllCsv(String nomOrganisation, String nomLot, String dateLot, MultipartFile csvDataCenter, MultipartFile csvEquipementPhysique, MultipartFile csvEquipementVirtuel, MultipartFile csvApplication, MultipartFile csvOperationNonIT, MultipartFile csvMessagerie, MultipartFile csvEntite) throws ValidationException { // Lecture & conversion - var resultatImport = importDonneesEntreePort.importCsv(nomOrganisation, nomLot, dateLot, csvDataCenter, csvEquipementPhysique, csvEquipementVirtuel, csvApplication, csvMessagerie, csvEntite); + var resultatImport = importDonneesEntreePort.importCsv(nomOrganisation, nomLot, dateLot, csvDataCenter, csvEquipementPhysique, csvEquipementVirtuel, csvApplication, csvOperationNonIT, csvMessagerie, csvEntite); saveDonneesEntreePort.save(resultatImport.getDonneesEntree()); @@ -152,6 +157,7 @@ public class ImportCSVController implements ImportsApi { updateResultatImport(resultatImport, "equipement_physique", errorManagementPostSaveService.checkEquipementPhysiques(nomLot)); updateResultatImport(resultatImport, "equipement_virtuel", errorManagementPostSaveService.checkEquipementVirtuels(nomLot)); updateResultatImport(resultatImport, "application", errorManagementPostSaveService.checkApplications(nomLot)); + updateResultatImport(resultatImport, "operation_non_it", errorManagementPostSaveService.checkOperationsNonIT(nomLot)); return resultatImport.getRapports().stream() .map(donneesEntreeMapper::toRestDTO) diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/helper/Constants.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/helper/Constants.java index 9c448a70cffe1c8ae0f8feab903321da54a96f50..c44cef377f6eb20e82d3a1e5144ee3a0a88ee629 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/helper/Constants.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/helper/Constants.java @@ -7,5 +7,6 @@ public class Constants { public static final String TABLE_EQUIPEMENT_PHYSIQUE = "en_equipement_physique"; public static final String TABLE_EQUIPEMENT_VIRTUEL = "en_equipement_virtuel"; public static final String TABLE_APPLICATION = "en_application"; + public static final String TABLE_OPERATION_NON_IT = "en_operation_non_it"; public static final String TABLE_MESSAGERIE = "en_messagerie"; } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jdbc/SoumissionCalculPortJdbcImpl.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jdbc/SoumissionCalculPortJdbcImpl.java index 4e6095f9aad73f3e02cbd678d8e2b77fee9fc7d2..2427ca6e309c1c0447113a98b00d460f00e42e16 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jdbc/SoumissionCalculPortJdbcImpl.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jdbc/SoumissionCalculPortJdbcImpl.java @@ -35,6 +35,7 @@ public class SoumissionCalculPortJdbcImpl implements SoumissionCalculPort { jdbcTemplate.update(getUpdateStatementForTable(TABLE_DONNEES_ENTREES), STATUT_TRAITEMENT_A_INGERER, demandeCalcul.getNomLot(), STATUT_TRAITEMENT_EN_ATTENTE); rapport.setNbrDataCenter(jdbcTemplate.update(getUpdateStatementForTable(TABLE_DATA_CENTER), STATUT_TRAITEMENT_A_INGERER, demandeCalcul.getNomLot(), STATUT_TRAITEMENT_EN_ATTENTE)); rapport.setNbrEquipementPhysique(jdbcTemplate.update(getUpdateStatementForTable(TABLE_EQUIPEMENT_PHYSIQUE), STATUT_TRAITEMENT_A_INGERER, demandeCalcul.getNomLot(), STATUT_TRAITEMENT_EN_ATTENTE)); + rapport.setNbrOperationNonIT(jdbcTemplate.update(getUpdateStatementForTable(TABLE_OPERATION_NON_IT), STATUT_TRAITEMENT_A_INGERER, demandeCalcul.getNomLot(), STATUT_TRAITEMENT_EN_ATTENTE)); rapport.setNbrMessagerie(jdbcTemplate.update(getUpdateStatementForTable(TABLE_MESSAGERIE), STATUT_TRAITEMENT_A_INGERER, demandeCalcul.getNomLot(), STATUT_TRAITEMENT_EN_ATTENTE)); return rapport; } @@ -51,6 +52,7 @@ public class SoumissionCalculPortJdbcImpl implements SoumissionCalculPort { jdbcTemplate.update(getUpdateForRejeuStatementForTable(TABLE_DONNEES_ENTREES), STATUT_TRAITEMENT_A_INGERER, demandeCalcul.getNomLot()); rapport.setNbrDataCenter(jdbcTemplate.update(getUpdateForRejeuStatementForTable(TABLE_DATA_CENTER), STATUT_TRAITEMENT_A_INGERER, demandeCalcul.getNomLot())); rapport.setNbrEquipementPhysique(jdbcTemplate.update(getUpdateForRejeuStatementForTable(TABLE_EQUIPEMENT_PHYSIQUE), STATUT_TRAITEMENT_A_INGERER, demandeCalcul.getNomLot())); + rapport.setNbrOperationNonIT(jdbcTemplate.update(getUpdateForRejeuStatementForTable(TABLE_OPERATION_NON_IT), STATUT_TRAITEMENT_A_INGERER, demandeCalcul.getNomLot())); rapport.setNbrMessagerie(jdbcTemplate.update(getUpdateForRejeuStatementForTable(TABLE_MESSAGERIE), STATUT_TRAITEMENT_A_INGERER, demandeCalcul.getNomLot())); return rapport; } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/adapter/OperationNonITJpaAdapter.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/adapter/OperationNonITJpaAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..5249d07e7e45e14ae1c4bd02a9f11dc1df9d2ca3 --- /dev/null +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/adapter/OperationNonITJpaAdapter.java @@ -0,0 +1,31 @@ +package org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.adapter; + +import lombok.AllArgsConstructor; +import org.mte.numecoeval.expositiondonneesentrees.domain.model.OperationNonIT; +import org.mte.numecoeval.expositiondonneesentrees.domain.ports.output.EntreePersistencePort; +import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.repository.OperationNonITRepository; +import org.mte.numecoeval.expositiondonneesentrees.infrastructure.mapper.EntreeEntityMapper; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@AllArgsConstructor +public class OperationNonITJpaAdapter implements EntreePersistencePort<OperationNonIT> { + + OperationNonITRepository repository; + + EntreeEntityMapper entreeEntityMapper; + + @Override + public void save(OperationNonIT entree) { + repository.save(entreeEntityMapper.toEntity(entree)); + } + + @Override + public void saveAll(List<OperationNonIT> entrees) { + repository.saveAll(entreeEntityMapper.toEntityListOperationNonIT(entrees)); + } + + +} diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/adapter/SaveDonneesEntreeAdapter.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/adapter/SaveDonneesEntreeAdapter.java index 446463b9cb0f21ee842a65315f622338b97d2b9a..ae7f341761df6c036aaecce5e2d1160e4a7c614b 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/adapter/SaveDonneesEntreeAdapter.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/adapter/SaveDonneesEntreeAdapter.java @@ -26,6 +26,7 @@ public class SaveDonneesEntreeAdapter implements SaveDonneesEntreePort { private EntreePersistencePort<EquipementPhysique> equipementPhysiqueEntreePersistencePort; private EntreePersistencePort<EquipementVirtuel> equipementVirtuelEntreePersistencePort; private EntreePersistencePort<Application> applicationEntreePersistencePort; + private EntreePersistencePort<OperationNonIT> operationNonITEntreePersistencePort; private EntreePersistencePort<Messagerie> messagerieEntreePersistencePort; private EntreePersistencePort<Entite> entiteEntreePersistencePort; @@ -42,7 +43,6 @@ public class SaveDonneesEntreeAdapter implements SaveDonneesEntreePort { donneesEntree.getNomLot(), donneesEntree.getDateLot(), donneesEntree.getNomOrganisation() ); - Set<String> equipementsPhysiquesImpactes = new HashSet<>(); Set<String> csvEquipementPhysiques = new HashSet<>(); @@ -103,7 +103,15 @@ public class SaveDonneesEntreeAdapter implements SaveDonneesEntreePort { .map(Application::getNomEquipementPhysique) .collect(Collectors.toSet())); } - + if (!CollectionUtils.isEmpty(donneesEntree.getOperationsNonIT())) { + stopWatch = StopWatch.createStarted(); + operationNonITEntreePersistencePort.saveAll(donneesEntree.getOperationsNonIT()); + stopWatch.stop(); + log.info("Fin du traitement des {} objets Opérations non IT reçues en {} secondes", + donneesEntree.getOperationsNonIT().size(), + stopWatch.getTime(TimeUnit.SECONDS) + ); + } if (!CollectionUtils.isEmpty(donneesEntree.getMessageries())) { stopWatch = StopWatch.createStarted(); messagerieEntreePersistencePort.saveAll(donneesEntree.getMessageries()); diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/ApplicationEntity.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/ApplicationEntity.java index 687361b3c041c3da7f590e3d99599084f0d47dd2..c492326eef0a1f7ddae5aaa968633b750d236fb6 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/ApplicationEntity.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/ApplicationEntity.java @@ -1,17 +1,7 @@ package org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.entity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.SequenceGenerator; -import jakarta.persistence.Table; -import lombok.AllArgsConstructor; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; +import jakarta.persistence.*; +import lombok.*; import lombok.experimental.SuperBuilder; /** @@ -25,50 +15,56 @@ import lombok.experimental.SuperBuilder; @EqualsAndHashCode @Table(name = "EN_APPLICATION") @Entity -public class ApplicationEntity extends AbstractEntreeEntity{ - @Id - @GeneratedValue(generator = "SEQ_EN_APPLICATION", strategy = GenerationType.SEQUENCE) - @SequenceGenerator(name = "SEQ_EN_APPLICATION", sequenceName="SEQ_EN_APPLICATION",allocationSize=1000) - @Column(nullable = false) - private Long id; +public class ApplicationEntity extends AbstractEntreeEntity { + @Id + @GeneratedValue(generator = "SEQ_EN_APPLICATION", strategy = GenerationType.SEQUENCE) + @SequenceGenerator(name = "SEQ_EN_APPLICATION", sequenceName = "SEQ_EN_APPLICATION", allocationSize = 1000) + @Column(nullable = false) + private Long id; - /** - * Nom de l'application - */ - private String nomApplication; + /** + * Nom de l'application + */ + private String nomApplication; - /** - * Type d'environnement de l'instance de l'application - */ - private String typeEnvironnement; + /** + * Type d'environnement de l'instance de l'application + */ + private String typeEnvironnement; - /** - * Référence de l'équipement virtuel rattaché - */ - private String nomEquipementVirtuel; + /** + * Référence de l'équipement virtuel rattaché + */ + private String nomEquipementVirtuel; - /** - * Référence de l'équipement physique rattaché - */ - private String nomEquipementPhysique; + /** + * Référence de l'équipement physique rattaché + */ + private String nomEquipementPhysique; - /** - * Nom de la source de données pour l'équipement physique rattaché - */ - private String nomSourceDonneeEquipementVirtuel; + /** + * Nom de la source de données pour l'équipement physique rattaché + */ + private String nomSourceDonneeEquipementVirtuel; - /** - * Domaine ou catégorie principale de l'application - */ - private String domaine; + /** + * Domaine ou catégorie principale de l'application + */ + private String domaine; - /** - * Domaine ou catégorie secondaire de l'application - */ - private String sousDomaine; + /** + * Domaine ou catégorie secondaire de l'application + */ + private String sousDomaine; + + /** + * Nom de l'entité rattachée à l'application + */ + private String nomEntite; + + /** + * Qualité de la donnée collectée + */ + private String qualite; - /** - * Nom de l'entité rattachée à l'application - */ - private String nomEntite; } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/DataCenterEntity.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/DataCenterEntity.java index 6f9a6f4b8c6d4d2bbe6420bcad1de36d24fe5d84..c354056ac21f5b64582766a33b45f35ed5974385 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/DataCenterEntity.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/DataCenterEntity.java @@ -1,12 +1,6 @@ package org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.entity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.SequenceGenerator; -import jakarta.persistence.Table; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -24,7 +18,7 @@ public class DataCenterEntity extends AbstractEntreeEntity { @Id @GeneratedValue(generator = "SEQ_EN_DATA_CENTER", strategy = GenerationType.SEQUENCE) - @SequenceGenerator(name = "SEQ_EN_DATA_CENTER", sequenceName="SEQ_EN_DATA_CENTER",allocationSize=1000) + @SequenceGenerator(name = "SEQ_EN_DATA_CENTER", sequenceName = "SEQ_EN_DATA_CENTER", allocationSize = 1000) @Column(nullable = false) protected Long id; @@ -33,6 +27,6 @@ public class DataCenterEntity extends AbstractEntreeEntity { private Double pue; private String localisation; private String nomEntite; - + private String qualite; } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/DonneesEntreesEntity.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/DonneesEntreesEntity.java index 277304f7f6a6c0f1059c6b3399745c544b8371d2..bd22d5dcc795f261b2a96884559b1fde25c64c9e 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/DonneesEntreesEntity.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/DonneesEntreesEntity.java @@ -1,12 +1,6 @@ package org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.entity; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.SequenceGenerator; -import jakarta.persistence.Table; +import jakarta.persistence.*; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -55,4 +49,9 @@ public class DonneesEntreesEntity extends AbstractEntreeEntity { */ private Long nbrMessageries; + /** + * Méthode de calcul de la durée d'usage des équipements physique + */ + private String dureeUsage; + } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/EquipementPhysiqueEntity.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/EquipementPhysiqueEntity.java index 75cd3f41f5ae926f32741753975805881da072f4..fb4a9d7f5fd1ed6b2b5cdfb20d7e68e81a8a87e6 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/EquipementPhysiqueEntity.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/EquipementPhysiqueEntity.java @@ -34,6 +34,9 @@ public class EquipementPhysiqueEntity extends AbstractEntreeEntity { private String utilisateur; private LocalDate dateAchat; private LocalDate dateRetrait; + private Double dureeUsageInterne; + private Double dureeUsageAmont; + private Double dureeUsageAval; private String nbCoeur; private String nomCourtDatacenter; private Double nbJourUtiliseAn; @@ -49,4 +52,6 @@ public class EquipementPhysiqueEntity extends AbstractEntreeEntity { private Double quantite; private String modeUtilisation; private Double tauxUtilisation; + private String qualite; + } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/EquipementVirtuelEntity.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/EquipementVirtuelEntity.java index 3fb7ec065b1e355e278a0af92e21aebfa1a01991..77a29ffc0729d77746849bf989aa86788584e1a6 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/EquipementVirtuelEntity.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/EquipementVirtuelEntity.java @@ -30,4 +30,6 @@ public class EquipementVirtuelEntity extends AbstractEntreeEntity { private String typeEqv; private Double capaciteStockage; private Double cleRepartition; + private String qualite; + } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/OperationNonITEntity.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/OperationNonITEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..4fee9d7d8d779657e0a4416aeeb4a23b7d8ae1a0 --- /dev/null +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/entity/OperationNonITEntity.java @@ -0,0 +1,37 @@ +package org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.entity; + +import jakarta.persistence.*; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import lombok.experimental.SuperBuilder; + +@Getter +@Setter +@SuperBuilder +@NoArgsConstructor +@AllArgsConstructor +@Table(name = "EN_OPERATION_NON_IT") +@Entity +public class OperationNonITEntity extends AbstractEntreeEntity { + + @Id + @GeneratedValue(generator = "SEQ_EN_OPERATION_NON_IT", strategy = GenerationType.SEQUENCE) + @SequenceGenerator(name = "SEQ_EN_OPERATION_NON_IT", sequenceName = "SEQ_EN_OPERATION_NON_IT", allocationSize = 1000) + @Column(nullable = false) + private Long id; + @Column(name = "nom_item_non_it") + private String nomItemNonIT; + private Double quantite; + private String type; + private Double dureeDeVie; + private String localisation; + private String nomEntite; + private String nomSourceDonnee; + private String nomCourtDatacenter; + private String description; + private Double consoElecAnnuelle; + private String qualite; + +} diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/repository/DonneesEntreesRepository.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/repository/DonneesEntreesRepository.java index 1e08aeec5893cd6b4fe86fa8c14f8e18e23060ee..053371f23dee9ad46d4315f7c7b2b8c07488183a 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/repository/DonneesEntreesRepository.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/repository/DonneesEntreesRepository.java @@ -2,9 +2,23 @@ package org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.repositor import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.entity.DonneesEntreesEntity; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; @Repository -public interface DonneesEntreesRepository extends JpaRepository<DonneesEntreesEntity,Long> -{ +public interface DonneesEntreesRepository extends JpaRepository<DonneesEntreesEntity, Long> { + @Transactional + @Modifying + @Query(""" + UPDATE DonneesEntreesEntity dee + SET dee.dureeUsage = :dureeUsage + WHERE dee.nomLot = :nomLot + """) + int updateDonneesEntreesDureeUsage( + @Param("dureeUsage") String dureeUsage, + @Param("nomLot") String nomLot + ); } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/repository/OperationNonITRepository.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/repository/OperationNonITRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..8d7dd22d3aacf4115aa686d5c24d7e7832469f38 --- /dev/null +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/repository/OperationNonITRepository.java @@ -0,0 +1,27 @@ +package org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.repository; + +import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.entity.OperationNonITEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface OperationNonITRepository extends JpaRepository<OperationNonITEntity, Long> { + @Query(value = """ + WITH datacenters AS ( + SELECT nom_court_datacenter FROM en_data_center WHERE nom_lot = ?1 + ) + SELECT nom_item_non_it FROM en_operation_non_it eoni + WHERE nom_lot = ?1 + AND nom_court_datacenter is NOT NULL + AND nom_court_datacenter NOT IN (SELECT nom_court_datacenter FROM datacenters) + ORDER BY nom_item_non_it + """, nativeQuery = true) + List<String> getOperationNonITAvecMauvaisNomCourtDatacenter(String nomLot); + + @Query("select id from #{#entityName} where nomLot = ?1 and statutTraitement = ?2") + List<Long> getIdsByNomLotAndStatutTraitement(String nomLot, String statutTraitement); + +} diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/mapper/EntreeEntityMapper.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/mapper/EntreeEntityMapper.java index 4e2ee607e9fa0f40b02071060eb5d63337c880c9..749e0d698b0d4c19b532d562073fb4f8d376ce19 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/mapper/EntreeEntityMapper.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/mapper/EntreeEntityMapper.java @@ -2,20 +2,8 @@ package org.mte.numecoeval.expositiondonneesentrees.infrastructure.mapper; import org.mapstruct.Mapper; import org.mapstruct.Mapping; -import org.mte.numecoeval.expositiondonneesentrees.domain.model.Application; -import org.mte.numecoeval.expositiondonneesentrees.domain.model.DataCenter; -import org.mte.numecoeval.expositiondonneesentrees.domain.model.DonneesEntree; -import org.mte.numecoeval.expositiondonneesentrees.domain.model.Entite; -import org.mte.numecoeval.expositiondonneesentrees.domain.model.EquipementPhysique; -import org.mte.numecoeval.expositiondonneesentrees.domain.model.EquipementVirtuel; -import org.mte.numecoeval.expositiondonneesentrees.domain.model.Messagerie; -import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.entity.ApplicationEntity; -import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.entity.DataCenterEntity; -import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.entity.DonneesEntreesEntity; -import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.entity.EntiteEntity; -import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.entity.EquipementPhysiqueEntity; -import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.entity.EquipementVirtuelEntity; -import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.entity.MessagerieEntity; +import org.mte.numecoeval.expositiondonneesentrees.domain.model.*; +import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.entity.*; import java.util.List; @@ -23,31 +11,63 @@ import java.util.List; public interface EntreeEntityMapper { DonneesEntreesEntity toEntity(DonneesEntree domain); + DataCenterEntity toEntity(DataCenter domain); + EquipementPhysiqueEntity toEntity(EquipementPhysique domain); + @Mapping(target = "vCPU", source = "VCPU") EquipementVirtuelEntity toEntity(EquipementVirtuel domain); + ApplicationEntity toEntity(Application domain); + MessagerieEntity toEntity(Messagerie domain); + EntiteEntity toEntity(Entite domain); + + OperationNonITEntity toEntity(OperationNonIT domain); + List<DataCenterEntity> toEntityListDataCenter(List<DataCenter> domains); + List<EquipementPhysiqueEntity> toEntityListEquipementPhysique(List<EquipementPhysique> domains); + List<EquipementVirtuelEntity> toEntityListEquipementVirtuel(List<EquipementVirtuel> domains); + List<ApplicationEntity> toEntityListApplication(List<Application> domains); + List<MessagerieEntity> toEntityListMessagerie(List<Messagerie> domains); + List<EntiteEntity> toEntityListEntite(List<Entite> domains); + List<OperationNonITEntity> toEntityListOperationNonIT(List<OperationNonIT> domains); + DonneesEntree toDomain(DonneesEntreesEntity entity); + DataCenter toDomain(DataCenterEntity entity); + EquipementPhysique toDomain(EquipementPhysiqueEntity entity); + EquipementVirtuel toDomain(EquipementVirtuelEntity entity); + Application toDomain(ApplicationEntity entity); + Messagerie toDomain(MessagerieEntity entity); + Entite toDomain(Entite entity); + + OperationNonIT toDomain(OperationNonITEntity entity); + List<DataCenter> toDomainListDataCenter(List<DataCenterEntity> entities); + List<EquipementPhysique> toDomainListEquipementPhysique(List<EquipementPhysiqueEntity> entities); + List<EquipementVirtuel> toDomainListEquipementVirtuel(List<EquipementVirtuelEntity> entities); + List<Application> toDomainListApplication(List<ApplicationEntity> entities); + List<Messagerie> toDomainListMessagerie(List<MessagerieEntity> entities); + List<Entite> toDomainListEntite(List<EntiteEntity> entities); + + List<OperationNonIT> toDomainListOperationNonIT(List<OperationNonITEntity> entities); } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/DefaultValueService.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/DefaultValueService.java new file mode 100644 index 0000000000000000000000000000000000000000..77b3e69679feabf969710e994beee95fa5d1afaa --- /dev/null +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/DefaultValueService.java @@ -0,0 +1,31 @@ +package org.mte.numecoeval.expositiondonneesentrees.infrastructure.service; + +import lombok.AllArgsConstructor; +import org.mte.numecoeval.expositiondonneesentrees.domain.model.EquipementPhysique; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@AllArgsConstructor +public class DefaultValueService { + + @Value("#{'${constraints.mode-utilisation}'.split(',')}") + private List<String> modeUtilisationList; + + /** + * fonction à effet de bord qui permet de réaffecter certaines variables à leur valeur par défaut lorsque leur valeur initiale est incorrecte (créé un avertissement) + * + * @param equipementPhysique un equipementPhysique à enregistrer en base + */ + public void setEquipementValeurDefaut(EquipementPhysique equipementPhysique) { + if (equipementPhysique.getModeUtilisation() != null && !modeUtilisationList.contains(equipementPhysique.getModeUtilisation())) { + equipementPhysique.setModeUtilisation(null); + } + Double taux = equipementPhysique.getTauxUtilisation(); + if (taux != null && (taux < 0 || taux > 1)) { + equipementPhysique.setTauxUtilisation(null); + } + } +} diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/ErrorManagementPostSaveService.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/ErrorManagementPostSaveService.java index e10fe962bdff06ffae7153267dd9202b9faa20c7..692f72c7812fc5b64c925e888269af7c61bd7333 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/ErrorManagementPostSaveService.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/ErrorManagementPostSaveService.java @@ -5,6 +5,7 @@ import org.mte.numecoeval.expositiondonneesentrees.infrastructure.config.Message import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.repository.ApplicationRepository; import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.repository.EquipementPhysiqueRepository; import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.repository.EquipementVirtuelRepository; +import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.repository.OperationNonITRepository; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -15,10 +16,11 @@ import java.util.List; public class ErrorManagementPostSaveService { final MessageProperties messageProperties; - final EquipementPhysiqueRepository equipementPhysiqueRepository; final EquipementVirtuelRepository equipementVirtuelRepository; final ApplicationRepository applicationRepository; + final OperationNonITRepository operationNonITRepository; + public List<String> checkEquipementPhysiques(String nomLot) { // CA 3.2 @@ -46,9 +48,13 @@ public class ErrorManagementPostSaveService { result.addAll(applicationRepository.getApplicationSansEquipementPhysique(nomLot).stream() .map(equipementVirtuel -> messageProperties.getMessages().get("APPLICATION_AVEC_EQUIPEMENT_VIRTUEL_INCONNU").formatted(equipementVirtuel)) .toList()); - + return result; } - + public List<String> checkOperationsNonIT(String nomLot) { + return operationNonITRepository.getOperationNonITAvecMauvaisNomCourtDatacenter(nomLot).stream() + .map(itemNonIT -> messageProperties.getMessages().get("ITEM_NOM_DATACENTER_INCONNU").formatted(itemNonIT)) + .toList(); + } } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/ErrorManagementService.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/ErrorManagementService.java index 473a1a4e1fed90602ece904dcfee3464a3919c43..f0faabc32f03e6e6460dc04da04e83c38fd38c0b 100644 --- a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/ErrorManagementService.java +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/ErrorManagementService.java @@ -5,13 +5,16 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.mte.numecoeval.expositiondonneesentrees.domain.model.DataCenter; import org.mte.numecoeval.expositiondonneesentrees.domain.model.EquipementPhysique; +import org.mte.numecoeval.expositiondonneesentrees.domain.model.OperationNonIT; import org.mte.numecoeval.expositiondonneesentrees.domain.ports.output.ReferentielServicePort; import org.mte.numecoeval.expositiondonneesentrees.infrastructure.config.MessageProperties; import org.mte.numecoeval.expositiondonneesentrees.referentiels.generated.api.model.CorrespondanceRefEquipementDTO; +import org.mte.numecoeval.expositiondonneesentrees.utils.Constants; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; @@ -26,6 +29,40 @@ public class ErrorManagementService { @Value("#{'${constraints.mode-utilisation}'.split(',')}") private List<String> modeUtilisationList; + /** + * Vérifie si la qualité de la donnée d'un item d'un inventaire fait partie de cette enum (BASSE, MOYENNE, HAUTE) + * si ce n'est pas le cas, on lance un avertissement + * la valeur qualite est déjà en majuscule + * + * @param qualite la qualité en majuscule + * @param type le type d'item + * @param nom le nom de l'équipement + * @return l'avertissement associé ou null + */ + public String checkQualiteDonnees(String qualite, String type, String nom) { + if (qualite == null) return null; + if (Constants.QUALITES_DONNEES.contains(qualite)) return null; + return messageProperties.getMessages().get("QUALITE_INVALIDE").formatted(type, nom, qualite); + } + + /** + * Vérifie si la syntaxe du nom fourni comme typeItem (dans l'inventaire d'un équipement physique ou d'une opération non IT) est correcte + * C'est à dire que le type ne contient pas les caractères '/' ou '\'. + * si ce n'est pas le cas, on lance une erreur + * + * @param type la qualité en majuscule + * @param nomItem le nom d'item : équipement ou opération non IT + * @param nom le nom de l'équipement + * @return l'avertissement associé ou null + */ + public String checkNomTypeItem(String type, String nomItem, String nom) { + if (type == null) return null; + if (!type.contains("/") && !type.contains("\\")) { + return null; + } + return messageProperties.getMessages().get("TYPE_ITEM_INVALIDE").formatted(nomItem, nom, type); + } + /** * Vérifie si la localisation du datacenter existe dans la table ref_MixElec.pays * @@ -58,7 +95,7 @@ public class ErrorManagementService { if (StringUtils.isNotBlank(equipementPhysique.getPaysDUtilisation()) && !referentielServicePort.hasMixElec(equipementPhysique.getPaysDUtilisation())) { - erreurs.add(messageProperties.getMessages().get("EQUIPEMENT_MIX_ELEC_LOCALISATION_INCONNUE").formatted(equipementPhysique.getPaysDUtilisation(), equipementPhysique.getNomEquipementPhysique())); + erreurs.add(messageProperties.getMessages().get("ITEM_MIX_ELEC_LOCALISATION_INCONNUE").formatted(equipementPhysique.getPaysDUtilisation(), equipementPhysique.getNomEquipementPhysique())); } String refEquipement = refEquipementParDefaut; @@ -84,31 +121,69 @@ public class ErrorManagementService { for (var etape : etapes) { var impact = referentielServicePort.getImpactEquipement(refEquipement, critere.getNomCritere(), etape.getCode()); if (impact == null) { - avertissements.add(messageProperties.getMessages().get("EQUIPEMENT_IMPACT_INCONNU").formatted(refEquipement, etape.getCode(), critere.getNomCritere())); + avertissements.add(messageProperties.getMessages().get("ITEM_IMPACT_INCONNU").formatted(refEquipement, etape.getCode(), critere.getNomCritere())); } } } // CA 3.1 - // L'ajout d'un équipement dont le date de retrait (equipementPhysique.DateRetrait) précède la date d'achat (equipementPhysique.DateAchat) + // L'ajout d'un équipement dont la date de retrait (equipementPhysique.DateRetrait) précède la date d'achat (equipementPhysique.DateAchat) if (equipementPhysique.getDateAchat() != null && equipementPhysique.getDateRetrait() != null && equipementPhysique.getDateAchat().isAfter(equipementPhysique.getDateRetrait())) { erreurs.add(messageProperties.getMessages().get("EQUIPEMENT_DATE_INCOHERENTE").formatted(equipementPhysique.getNomEquipementPhysique())); } - //CA 4.1 - //L'ajout d'un équipement dont le mode d'utilisation est autre que COPE, BYOD ou null + // CA 4.1 + // L'ajout d'un équipement dont la duree d'usage interne est négative + if (equipementPhysique.getDureeUsageInterne() != null && equipementPhysique.getDureeUsageInterne() <= 0) { + erreurs.add(messageProperties.getMessages().get("EQUIPEMENT_DUREE_USAGE_INTERNE_INCOHERENTE").formatted(equipementPhysique.getNomEquipementPhysique())); + } + if (equipementPhysique.getDureeUsageAmont() != null && equipementPhysique.getDureeUsageAmont() < 0) { + erreurs.add(messageProperties.getMessages().get("EQUIPEMENT_DUREE_USAGE_INCOHERENTE").formatted("amont", equipementPhysique.getNomEquipementPhysique())); + } + if (equipementPhysique.getDureeUsageAval() != null && equipementPhysique.getDureeUsageAval() < 0) { + erreurs.add(messageProperties.getMessages().get("EQUIPEMENT_DUREE_USAGE_INCOHERENTE").formatted("aval", equipementPhysique.getNomEquipementPhysique())); + } + //CA 5.1 + // L'ajout d'un équipement dont le mode d'utilisation est autre que COPE, BYOD ou null if (equipementPhysique.getModeUtilisation() != null && !modeUtilisationList.contains(equipementPhysique.getModeUtilisation())) { avertissements.add(messageProperties.getMessages().get("EQUIPEMENT_MODE_UTILISATION_INCONNU").formatted(equipementPhysique.getModeUtilisation())); } - //CA 5.1 - //L'ajout d'un équipement dont le taux d'utilisation n'est pas compris entre 0 et 1 + //CA 6.1 + // L'ajout d'un équipement dont le taux d'utilisation n'est pas compris entre 0 et 1 Double taux = equipementPhysique.getTauxUtilisation(); if (taux != null && (taux < 0 || taux > 1)) { avertissements.add(messageProperties.getMessages().get("EQUIPEMENT_TAUX_UTILISATION_INVALIDE").formatted(taux)); } - return Pair.of(erreurs, avertissements); } + /** + * Vérifie une operation non IT + * + * @param operationNonIT l'equipement physique + * @param type la reference d'equipement par default + * @return la paire (erreurs, avertissements) + */ + public Pair<List<String>, List<String>> checkOperationNonIT(OperationNonIT operationNonIT, String type) { + var erreurs = new ArrayList<String>(); + var avertissements = new HashSet<String>(); + // L'ajout d'une operation non it dont le type n'est pas renseigné sort une erreur + if (StringUtils.isBlank(type)) { + erreurs.add(messageProperties.getMessages().get("ITEM_CORRESPONDANCE_INCONNUE").formatted(operationNonIT.getNomItemNonIT(), operationNonIT.getType())); + } else { + // L'ajout d'une opération non it dont la référence d'impact (déterminée à partir de la table ref_type_item) est nulle sort un warning + var etapes = referentielServicePort.getAllEtapes(); + var criteres = referentielServicePort.getAllCriteres(); + for (var critere : criteres) { + for (var etape : etapes) { + var impact = referentielServicePort.getFacteurCaracterisation(critere.getNomCritere(), etape.getCode(), type); + if (impact == null) { + avertissements.add(messageProperties.getMessages().get("ITEM_IMPACT_INCONNU").formatted(type, etape.getCode(), critere.getNomCritere())); + } + } + } + } + return Pair.of(erreurs, avertissements.stream().toList()); + } } diff --git a/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/utils/Constants.java b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/utils/Constants.java new file mode 100644 index 0000000000000000000000000000000000000000..ca102130363923e1592bff37a46cec6353df60e5 --- /dev/null +++ b/services/api-expositiondonneesentrees/src/main/java/org/mte/numecoeval/expositiondonneesentrees/utils/Constants.java @@ -0,0 +1,8 @@ +package org.mte.numecoeval.expositiondonneesentrees.utils; + +import java.util.List; + +public class Constants { + public static final List<String> QUALITES_DONNEES = List.of("BASSE", "MOYENNE", "HAUTE"); + +} diff --git a/services/api-expositiondonneesentrees/src/main/resources/application.yaml b/services/api-expositiondonneesentrees/src/main/resources/application.yaml index c41b811a2864a5167ae0c7222e2dd8da0d123463..ea08d244375722274fda3c213d7d1196e14a703d 100644 --- a/services/api-expositiondonneesentrees/src/main/resources/application.yaml +++ b/services/api-expositiondonneesentrees/src/main/resources/application.yaml @@ -73,20 +73,29 @@ caching: statutDesCalculs: "PT10S" referentiels: "PT10M" +#Variables internes du composant +regle-par-defaut-duree-usage: "FIXE" + messages: LIGNE_INCONSISTENTE: "Fichier %s : La ligne n°%d n'est pas consistente avec les headers du fichier" LIGNE_INCORRECTE: "Fichier %s : La ligne n°%d est incorrecte pour l'objet %s requise" - TYPE_EQUIPEMENT_INCONNU: "Le type d'équipement %s correspondant à l'équipement %s n'existe pas dans la table des références ref_TypeEquipement" - EQUIPEMENT_MIX_ELEC_LOCALISATION_INCONNUE: "Le pays %s correspondant à l'équipement physique %s n'existe pas dans la table des mix électriques ref_MixElec.pays" + TYPE_ITEM_INCONNU: "Le type d'item %s correspondant à l'item %s n'existe pas dans la table des références ref_type_item" + ITEM_MIX_ELEC_LOCALISATION_INCONNUE: "La localisation %s correspondant à l'item %s n'existe pas dans la table des mix électriques ref_MixElec.pays" DATACENTER_MIX_ELEC_LOCALISATION_INCONNUE: "La localisation %s du centre de données %s n'existe pas dans la table des mix électriques ref_MixElec.pays" - EQUIPEMENT_CORRESPONDANCE_INCONNUE: "L'équipement %s de type %s ne possède pas de référence d'équipement par défaut dans la table ref_typeEquipement et pas de correspondance dans la table ref_CorrespondanceRefEqP" - EQUIPEMENT_IMPACT_INCONNU: "L'impact de l'équipement de référence %s pour l'étape %s et le critère %s ne pourra pas être calculé en raison de l'absence de facteur d'impact sur l'équipement" + ITEM_CORRESPONDANCE_INCONNUE: "L'item %s de type %s ne possède pas de référence d'item par défaut dans la table ref_type_item" + EQUIPEMENT_CORRESPONDANCE_INCONNUE: "L'équipement %s de type %s ne possède pas de référence d'équipement par défaut dans la table ref_type_item et pas de correspondance dans la table ref_correspondance_ref_eqp" + ITEM_IMPACT_INCONNU: "L'impact de l'item de référence %s pour l'étape %s et le critère %s ne pourra pas être calculé en raison de l'absence de facteur d'impact sur cet item" EQUIPEMENT_DATE_INCOHERENTE: "L'âge de l'équipement %s ne peut être calculé car sa date de retrait précède sa date d'achat" + EQUIPEMENT_DUREE_USAGE_INTERNE_INCOHERENTE: "La durée d'usage interne de l'équipement %s est négative ou nulle donc invalide" + EQUIPEMENT_DUREE_USAGE_INCOHERENTE: "La durée d'usage %s de l'équipement %s est négative donc invalide" EQUIPEMENT_MODE_UTILISATION_INCONNU: "Le mode d'utilisation renseigné '%s' est inconnu du référentiel" EQUIPEMENT_TAUX_UTILISATION_INVALIDE: "Le taux d'utilisation renseigné '%s' n'est pas valide, il doit être compris entre 0 et 1, le taux par défaut sera appliqué." EQUIPEMENT_DATACENTER_INCONNU: "L'équipement %s n'est lié à aucun datacenter" + ITEM_NOM_DATACENTER_INCONNU: "Le nom court datacenter de l'item '%s' n'est pas dans la table datacenter" EQUIPEMENT_VIRTUEL_INCONNU: "L'équipement virtuel %s n'est supporté par aucun équipement physique" APPLICATION_AVEC_EQUIPEMENT_PHYSIQUE_INCONNU: "L'application %s n'est supporté par aucun équipement physique" APPLICATION_AVEC_EQUIPEMENT_VIRTUEL_INCONNU: "L'application %s n'est supporté par aucun équipement virtuel" + QUALITE_INVALIDE: "%s '%s' possède une valeur de qualité invalide renseignée. La valeur '%s' est ignorée car elle n'est pas l'une de ces valeurs: BASSE, MOYENNE, HAUTE" + TYPE_ITEM_INVALIDE: "%s '%s' possède un type dont la valeur : '%s' est invalide. La valeur ne doit pas contenir les caractères '/' et '\\'." constraints: mode-utilisation: "BYOD,COPE" diff --git a/services/api-expositiondonneesentrees/src/main/resources/schema.sql b/services/api-expositiondonneesentrees/src/main/resources/schema.sql index a6b627e6429f87542aede23ed4b0521fd2c032aa..9f3d48f38da7a19d55b0ac172e629ebafd43cec3 100644 --- a/services/api-expositiondonneesentrees/src/main/resources/schema.sql +++ b/services/api-expositiondonneesentrees/src/main/resources/schema.sql @@ -11,23 +11,25 @@ CREATE TABLE IF NOT EXISTS en_donnees_entrees nbr_equipements_physiques int8 NULL, nbr_equipements_virtuels int8 NULL, nbr_messageries int8 NULL, + duree_usage varchar(255) NULL, CONSTRAINT en_donnees_entrees_pkey PRIMARY KEY (id) ); CREATE TABLE IF NOT EXISTS en_data_center ( - id int8 NOT NULL, - date_creation timestamp NULL, - date_update timestamp NULL, - date_lot date NULL, - nom_lot varchar(255) NULL, - nom_organisation varchar(255) NULL, - nom_source_donnee varchar(255) NULL, - localisation varchar(255) NULL, - nom_court_datacenter varchar(255) NULL, - nom_entite varchar(255) NULL, - nom_long_datacenter varchar(255) NULL, - pue float8 NULL, + id int8 NOT NULL, + date_creation timestamp NULL, + date_update timestamp NULL, + date_lot date NULL, + nom_lot varchar(255) NULL, + nom_organisation varchar(255) NULL, + nom_source_donnee varchar(255) NULL, + localisation varchar(255) NULL, + nom_court_datacenter varchar(255) NULL, + nom_entite varchar(255) NULL, + nom_long_datacenter varchar(255) NULL, + pue float8 NULL, + qualite varchar(255) NULL, CONSTRAINT en_data_center_pkey PRIMARY KEY (id) ); @@ -43,6 +45,9 @@ CREATE TABLE IF NOT EXISTS en_equipement_physique conso_elec_annuelle float8 NULL, date_achat date NULL, date_retrait date NULL, + duree_usage_interne float8 NULL, + duree_usage_amont float8 NULL, + duree_usage_aval float8 NULL, duree_vie_defaut float8 NULL, go_telecharge float4 NULL, modele varchar(255) NULL, @@ -59,6 +64,7 @@ CREATE TABLE IF NOT EXISTS en_equipement_physique utilisateur varchar(255) NULL, mode_utilisation varchar(255) NULL, taux_utilisation float8 NULL, + qualite varchar(255) NULL, CONSTRAINT en_equipement_physique_pkey PRIMARY KEY (id) ); @@ -75,27 +81,52 @@ CREATE TABLE IF NOT EXISTS en_equipement_virtuel nom_equipement_physique varchar(255) NULL, nom_equipement_virtuel varchar(255) NULL, vcpu int4 NULL, + qualite varchar(255) NULL, CONSTRAINT en_equipement_virtuel_pkey PRIMARY KEY (id) ); CREATE TABLE IF NOT EXISTS en_application ( - id int8 NOT NULL, - date_creation timestamp NULL, - date_lot date NULL, - nom_lot varchar(255) NULL, - nom_organisation varchar(255) NULL, - nom_source_donnee varchar(255) NULL, - domaine varchar(255) NULL, - nom_application varchar(255) NULL, - nom_entite varchar(255) NULL, - nom_equipement_virtuel varchar(255) NULL, - nom_equipement_physique varchar(255) NULL, - sous_domaine varchar(255) NULL, - type_environnement varchar(255) NULL, + id int8 NOT NULL, + date_creation timestamp NULL, + date_lot date NULL, + nom_lot varchar(255) NULL, + nom_organisation varchar(255) NULL, + nom_source_donnee varchar(255) NULL, + domaine varchar(255) NULL, + nom_application varchar(255) NULL, + nom_entite varchar(255) NULL, + nom_equipement_virtuel varchar(255) NULL, + nom_equipement_physique varchar(255) NULL, + sous_domaine varchar(255) NULL, + type_environnement varchar(255) NULL, + qualite varchar(255) NULL, CONSTRAINT en_application_pkey PRIMARY KEY (id) ); +CREATE TABLE IF NOT EXISTS en_operation_non_it +( + id int8 NOT NULL, + date_creation timestamp NULL, + date_update timestamp NULL, + date_lot date NULL, + nom_lot varchar(255) NULL, + nom_organisation varchar(255) NULL, + nom_source_donnee varchar(255) NULL, + nom_item_non_it varchar(255) NULL, + quantite float8 NULL, + type varchar(255) NULL, + duree_de_vie float8 NULL, + localisation varchar(255) NULL, + nom_entite varchar(255) NULL, + nom_court_datacenter varchar(255) NULL, + description varchar(255) NULL, + conso_elec_annuelle float8 NULL, + statut_traitement varchar(255) NULL, + qualite varchar(255) NULL, + CONSTRAINT en_operation_non_it_pkey PRIMARY KEY (id) +); + CREATE TABLE IF NOT EXISTS en_messagerie ( id int8 NOT NULL, @@ -162,6 +193,11 @@ ALTER TABLE IF EXISTS en_equipement_virtuel ADD COLUMN IF NOT EXISTS cle_reparti ALTER TABLE IF EXISTS en_equipement_physique ADD COLUMN IF NOT EXISTS stockage_total_virtuel float8; ALTER TABLE IF EXISTS en_equipement_physique ADD COLUMN IF NOT EXISTS mode_utilisation varchar(255); ALTER TABLE IF EXISTS en_equipement_physique ADD COLUMN IF NOT EXISTS taux_utilisation float8; +ALTER TABLE IF EXISTS en_equipement_physique ADD COLUMN IF NOT EXISTS duree_usage_interne float8; +ALTER TABLE IF EXISTS en_equipement_physique ADD COLUMN IF NOT EXISTS duree_usage_amont float8; +ALTER TABLE IF EXISTS en_equipement_physique ADD COLUMN IF NOT EXISTS duree_usage_aval float8; + +ALTER TABLE IF EXISTS en_donnees_entrees ADD COLUMN IF NOT EXISTS duree_usage varchar(255); -- Creation indexes -- Accelere la recuperation des donnees depuis EquipementPhysiqueIntegrationConfig.java @@ -169,6 +205,11 @@ CREATE INDEX IF NOT EXISTS idx_en_equipement_physique_statut_traitement ON en_eq -- Accelere le count du volume des calculs - api-expositiondonneesentrees CREATE INDEX IF NOT EXISTS idx_en_equipement_physique_nom_lot ON en_equipement_physique (nom_lot); +-- Accelere la recuperation des donnees depuis OperationNonITIntegrationConfig.java +CREATE INDEX IF NOT EXISTS idx_en_operation_non_it_statut_traitement ON en_operation_non_it (statut_traitement); +-- Accelere le count du volume des calculs - api-expositiondonneesentrees +CREATE INDEX IF NOT EXISTS idx_en_operation_non_it_nom_lot ON en_operation_non_it (nom_lot); + -- Indexes pour api-event-calculs -- Accelere la recuperation des equipements virtuels d'un equipement physique CREATE INDEX IF NOT EXISTS idx_en_equipement_virtuel_nom_equipement_physique ON en_equipement_virtuel (nom_equipement_physique); diff --git a/services/api-expositiondonneesentrees/src/main/resources/static/openapi.yaml b/services/api-expositiondonneesentrees/src/main/resources/static/openapi.yaml index 821abfa69dc5d0dfdf300e14f99f09649aae2c83..4eb839bcf5867a26c1e30279baa5c0d16fa9741f 100644 --- a/services/api-expositiondonneesentrees/src/main/resources/static/openapi.yaml +++ b/services/api-expositiondonneesentrees/src/main/resources/static/openapi.yaml @@ -38,19 +38,19 @@ paths: "500": description: Erreur interne du service content: - 'application/json': + "application/json": schema: $ref: "#/components/schemas/ErreurRest" "400": description: Contenu de la soumission incorrecte content: - 'application/json': + "application/json": schema: $ref: "#/components/schemas/ErreurRest" "200": description: Rapport d'import des données d'entrées content: - 'application/json': + "application/json": schema: $ref: "#/components/schemas/StatutCalculRest" /entrees/calculs/soumission: @@ -58,10 +58,21 @@ paths: summary: Endpoint de soumission de données d'entrées pour lancer les calculs dans NumEcoEval. description: | Endpoint de soumission de données d'entrées pour lancer les calculs dans NumEcoEval. + Vous pouvez choisir la méthode de calcul de la durée de vie des équipements qui sera utilisée pour le calcul grâce au paramètre dureeUsage qui peut prendre 2 valeurs : + <ul> + <li>FIXE : La méthode de calcul de la durée de vie se base sur l'attribut 'dureeUsageInterne' de l'équipement physique (méthode utilisée par défaut si le paramètre dureeUsage n'est pas renseigné). </li> + <li>REEL : La méthode de calcul de la durée de vie se base sur l'âge réel de l'équipement physique (dateRetrait-dateAchat). </li> + </ul> tags: - Calculs operationId: soumissionPourCalcul parameters: + - in: query + name: dureeUsage + schema: + $ref: "#/components/schemas/DureeUsage" + required: false + description: "Choix de la méthode de calcul de la durée d'usage : FIXE ou REEL" - in: query name: mode schema: @@ -71,26 +82,26 @@ paths: requestBody: required: true content: - 'application/json': + "application/json": schema: $ref: "#/components/schemas/DemandeCalculRest" responses: "500": description: Erreur interne du service content: - 'application/json': + "application/json": schema: $ref: "#/components/schemas/ErreurRest" "400": description: Contenu de la soumission incorrecte content: - 'application/json': + "application/json": schema: $ref: "#/components/schemas/ErreurRest" "200": description: Rapport d'import des données d'entrées content: - 'application/json': + "application/json": schema: $ref: "#/components/schemas/RapportDemandeCalculRest" /entrees/calculs/rejeu: @@ -104,26 +115,26 @@ paths: requestBody: required: true content: - 'application/json': + "application/json": schema: $ref: "#/components/schemas/DemandeCalculRest" responses: "500": description: Erreur interne du service content: - 'application/json': + "application/json": schema: $ref: "#/components/schemas/ErreurRest" "400": description: Contenu de la soumission incorrecte content: - 'application/json': + "application/json": schema: $ref: "#/components/schemas/ErreurRest" "200": description: Rapport d'import des données d'entrées content: - 'application/json': + "application/json": schema: $ref: "#/components/schemas/RapportDemandeCalculRest" /entrees/json: @@ -138,26 +149,26 @@ paths: requestBody: required: true content: - 'application/json': + "application/json": schema: $ref: "#/components/schemas/DonneesEntreeRest" responses: "500": description: Erreur interne du service content: - 'application/json': + "application/json": schema: $ref: "#/components/schemas/ErreurRest" "400": description: Contenu de la soumission incorrecte content: - 'application/json': + "application/json": schema: $ref: "#/components/schemas/ErreurRest" "200": description: Rapport d'import des données d'entrées content: - 'application/json': + "application/json": schema: type: array items: @@ -169,24 +180,26 @@ paths: summary: Soumission de données d'entrées au format CSV pour calcul d'indicateurs description: | Endpoint de soumission des données d'entrées au format CSV pour le calcul d'indicateurs. - + La taille totale de tous les fichiers ne doit pas dépasser 10 Mo. <br/> - + Le séparateur des fichiers CSV est le point-virgule (;). <br/> - + Les colonnes facultatives sont notées entre parenthèses, toutes les autres sont obligatoires ! <br/> - - Le Header du CSV des data centers est : nomCourtDatacenter;nomLongDatacenter;pue;localisation;(nomEntite). <br/> - - Le Header du CSV des équipements physiques est : nomEquipementPhysique,modele;quantite;nomCourtDatacenter;dateAchat;dateRetrait;type;statut;paysDUtilisation;consoElecAnnuelle;utilisateur;(nomSourceDonnee);(nomEntite);nbCoeur;nbJourUtiliseAn;goTelecharge;(modeUtilisation);(tauxUtilisation). <br/> - - Le Header du CSV des équipements virtuels est : nomEquipementVirtuel;nomEquipementPhysique;(nomSourceDonneeEquipementPhysique);(cleRepartition);vCPU;cluster;(consoElecAnnuelle);(typeEqv);(capaciteStockage);(nomEntite). <br/> - - Le Header du CSV des application est : nomApplication;typeEnvironnement;(nomEquipementVirtuel);(nomSourceEquipementVirtuel);domaine;sousDomaine;(nomEntite);nomEquipementPhysique;(nomSourceDonnee). <br/> - + + Le Header du CSV des data centers est : nomCourtDatacenter;nomLongDatacenter;pue;localisation;(nomEntite);(qualite). <br/> + + Le Header du CSV des équipements physiques est : nomEquipementPhysique,modele;quantite;nomCourtDatacenter;(dateAchat);(dateRetrait);(dureeUsageInterne);(dureeUsageAmont);(dureeUsageAval);type;statut;paysDUtilisation;consoElecAnnuelle;utilisateur;(nomSourceDonnee);(nomEntite);nbCoeur;nbJourUtiliseAn;goTelecharge;(modeUtilisation);(tauxUtilisation);(qualite). <br/> + + Le Header du CSV des équipements virtuels est : nomEquipementVirtuel;nomEquipementPhysique;(nomSourceDonneeEquipementPhysique);(cleRepartition);vCPU;cluster;(consoElecAnnuelle);(typeEqv);(capaciteStockage);(nomEntite);(qualite). <br/> + + Le Header du CSV des application est : nomApplication;typeEnvironnement;(nomEquipementVirtuel);(nomSourceEquipementVirtuel);domaine;sousDomaine;(nomEntite);nomEquipementPhysique;(nomSourceDonnee);(qualite). <br/> + + Le Header du CSV des opérations non IT est : nomItemNonIT;quantite;type;dureeDeVie;localisation;(nomEntite);(nomSourceDonnee);nomCourtDatacenter;description;consoElecAnnuelle;(qualite). <br/> + Le Header du CSV de la messagerie est : nombreMailEmis;nombreMailEmisXDestinataires;volumeTotalMailEmis;MoisAnnee;(nomEntite). <br/> - - Le Header du CSV des entités est : nomEntite;nbCollaborateurs;responsableEntite;responsableNumeriqueResponsable. + + Le Header du CSV des entités est : nomEntite;nbCollaborateurs;responsableEntite;responsableNumeriqueResponsable. operationId: importCSV requestBody: @@ -216,6 +229,9 @@ paths: csvApplication: type: string format: binary + csvOperationNonIT: + type: string + format: binary csvMessagerie: type: string format: binary @@ -227,19 +243,19 @@ paths: "500": description: Erreur interne du service content: - 'application/json': + "application/json": schema: $ref: "#/components/schemas/ErreurRest" "400": description: Contenu de la soumission incorrecte content: - 'application/json': + "application/json": schema: $ref: "#/components/schemas/ErreurRest" "200": description: Rapport d'import des données d'entrées content: - 'application/json': + "application/json": schema: type: array items: @@ -270,6 +286,11 @@ components: - ASYNC - SYNC default: ASYNC + DureeUsage: + type: string + enum: + - FIXE + - REEL StatutCalculRest: description: Statut des calculs. properties: @@ -284,10 +305,13 @@ components: type: string equipementPhysique: description: "Bloc equipement physique" - $ref: '#/components/schemas/VolumeRest' + $ref: "#/components/schemas/VolumeRest" + operationNonIT: + description: "Bloc opération non it" + $ref: "#/components/schemas/VolumeRest" messagerie: description: "Bloc messagerie" - $ref: '#/components/schemas/VolumeRest' + $ref: "#/components/schemas/VolumeRest" VolumeRest: description: Volume type: object @@ -314,6 +338,9 @@ components: nbrApplication: description: Nombre d'application concernées type: integer + nbrOperationNonIT: + description: Nombre d'opérations non IT concernées + type: integer nbrMessagerie: description: Nombre d'éléments de messagerie concernés type: integer @@ -378,6 +405,10 @@ components: type: array items: $ref: "#/components/schemas/EquipementPhysiqueRest" + operationsNonIT: + type: array + items: + $ref: "#/components/schemas/OperationNonITRest" messageries: type: array items: @@ -407,6 +438,9 @@ components: nomSourceDonnee: description: "Nom de la source de la donnée" type: string + qualite: + description: "Qualite de la donnée collectée (BASSE, MOYENNE ou HAUTE)" + type: string EquipementPhysiqueRest: description: Représentation d'un équipement physique dans NumEcoEval properties: @@ -436,6 +470,15 @@ components: description: "" type: string format: date + dureeUsageInterne: + description: "" + type: number + dureeUsageAmont: + description: "" + type: number + dureeUsageAval: + description: "" + type: number nbCoeur: description: "" type: string @@ -470,6 +513,9 @@ components: description: "" items: $ref: "#/components/schemas/EquipementVirtuelRest" + qualite: + description: "Qualite de la donnée collectée (BASSE, MOYENNE ou HAUTE)" + type: string EquipementVirtuelRest: description: Représentation d'un équipement virtuel dans NumEcoEval properties: @@ -519,6 +565,9 @@ components: Consommation électrique annuelle de l'équipement virtuel. type: number format: double + qualite: + description: "Qualite de la donnée collectée (BASSE, MOYENNE ou HAUTE)" + type: string ApplicationRest: description: Représentation d'une application dans NumEcoEval properties: @@ -546,6 +595,46 @@ components: nomSourceDonneeEquipementVirtuel: description: "Nom de la source de la donnée pour l'équipement virtuel" type: string + qualite: + description: "Qualite de la donnée collectée (BASSE, MOYENNE ou HAUTE)" + type: string + OperationNonITRest: + description: Représentation d'une opération non IT dans NumEcoEval + properties: + nomItemNonIT: + description: "" + type: string + quantite: + description: "" + type: number + type: + description: "" + type: string + dureeDeVie: + description: "" + type: number + localisation: + description: "" + type: string + nomEntite: + description: "" + type: string + nomSourceDonnee: + description: "Nom de la source de la donnée" + type: string + nomCourtDatacenter: + description: "" + type: string + description: + description: "" + type: string + consoElecAnnuelle: + description: "" + type: number + format: double + qualite: + description: "Qualite de la donnée collectée (BASSE, MOYENNE ou HAUTE)" + type: string MessagerieRest: description: Représentation d'éléments de messagerie dans NumEcoEval properties: @@ -584,4 +673,4 @@ components: type: string nomSourceDonnee: description: "Nom de la source de la donnée" - type: string \ No newline at end of file + type: string diff --git a/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/domain/port/input/ImportDonneesEntreePortImplTest.java b/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/domain/port/input/ImportDonneesEntreePortImplTest.java index a92ad7fc80a14c33aa6e99fc16bb9a3482731263..d76085c3c6210d223353a2dd59718e7d798a036e 100644 --- a/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/domain/port/input/ImportDonneesEntreePortImplTest.java +++ b/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/domain/port/input/ImportDonneesEntreePortImplTest.java @@ -9,6 +9,7 @@ import org.mockito.MockitoAnnotations; import org.mte.numecoeval.expositiondonneesentrees.domain.model.*; import org.mte.numecoeval.expositiondonneesentrees.domain.ports.input.impl.ImportDonneesEntreePortImpl; import org.mte.numecoeval.expositiondonneesentrees.domain.ports.output.ReferentielServicePort; +import org.mte.numecoeval.expositiondonneesentrees.infrastructure.service.DefaultValueService; import org.mte.numecoeval.expositiondonneesentrees.infrastructure.service.ErrorManagementService; import org.springframework.web.multipart.MultipartFile; @@ -31,12 +32,12 @@ class ImportDonneesEntreePortImplTest { ImportDonneesEntreePortImpl importDonneesEntreePort; ErrorManagementService errorManagementService; - private List<String> modeUtilisationList; + DefaultValueService defaultValueService; @BeforeEach public void init() { MockitoAnnotations.openMocks(this); - importDonneesEntreePort = new ImportDonneesEntreePortImpl(referentielServicePort, errorManagementService, errorMessages, modeUtilisationList); + importDonneesEntreePort = new ImportDonneesEntreePortImpl(referentielServicePort, errorManagementService, defaultValueService, errorMessages); } @Test @@ -119,6 +120,26 @@ class ImportDonneesEntreePortImplTest { assertEquals("Le fichier CSV des Applications n'est pas trouvable.", resultImport.getKey().getErreurs().get(0)); } + @Test + void importOperationsNonIT_onIOException_shouldReturnReportWith1Error() throws IOException { + Mockito.when(fileToRead.getInputStream()).thenThrow(new IOException("Test")); + + Pair<RapportImport, List<OperationNonIT>> resultImport = importDonneesEntreePort.importOperationsNonIT(null, null, null, fileToRead); + + assertTrue(resultImport.getValue().isEmpty()); + assertEquals("Le fichier CSV des opérations non IT n'est pas lisible par le système.", resultImport.getKey().getErreurs().get(0)); + } + + @Test + void importOperationsNonIT_onFileNotFoundException_shouldReturnReportWith1Error() throws IOException { + Mockito.when(fileToRead.getInputStream()).thenThrow(new FileNotFoundException("Test")); + + Pair<RapportImport, List<OperationNonIT>> resultImport = importDonneesEntreePort.importOperationsNonIT(null, null, null, fileToRead); + + assertTrue(resultImport.getValue().isEmpty()); + assertEquals("Le fichier CSV des opérations non IT n'est pas trouvable.", resultImport.getKey().getErreurs().get(0)); + } + @Test void importMessageries_onIOException_shouldReturnReportWith1Error() throws IOException { Mockito.when(fileToRead.getInputStream()).thenThrow(new IOException("Test")); diff --git a/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/domain/port/input/StatutPourCalculPortImplTest.java b/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/domain/port/input/StatutPourCalculPortImplTest.java index 759780e146182eda45ed3fccfc9c797dc81d13f7..6f8f2676ce809eaeefeaa33a1c9804cd2daf810f 100644 --- a/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/domain/port/input/StatutPourCalculPortImplTest.java +++ b/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/domain/port/input/StatutPourCalculPortImplTest.java @@ -43,18 +43,23 @@ class StatutPourCalculPortImplTest { /* INPUT VOLUME MOCKED */ var volumeEqPhysique = new Volume(10L, 100L); + var volumeOpNonIT = new Volume(100L, 10L); var volumeMessagerie = new Volume(50L, 5000L); /* EXECUTE : params does not matter in the test */ - var actual = statutPourCalculPort.statutCalculs(volumeEqPhysique, volumeMessagerie); + var actual = statutPourCalculPort.statutCalculs(volumeEqPhysique, volumeOpNonIT, volumeMessagerie); var expected = StatutCalculRest.builder() .statut(StatutCalculRest.StatutEnum.EN_COURS) - .etat("98%") + .etat("96%") .equipementPhysique(VolumeRest.builder() .nbEnCours(10) .nbTraite(100) .build()) + .operationNonIT(VolumeRest.builder() + .nbEnCours(100) + .nbTraite(10) + .build()) .messagerie(VolumeRest.builder() .nbEnCours(50) .nbTraite(5000) @@ -71,10 +76,11 @@ class StatutPourCalculPortImplTest { /* INPUT VOLUME MOCKED */ var volumeEqPhysique = new Volume(0L, 100L); + var volumeOperationNonIT = new Volume(0L, 100L); var volumeMessagerie = new Volume(0L, 5000L); /* EXECUTE : params does not matter in the test */ - var actual = statutPourCalculPort.statutCalculs(volumeEqPhysique, volumeMessagerie); + var actual = statutPourCalculPort.statutCalculs(volumeEqPhysique, volumeOperationNonIT, volumeMessagerie); var expected = StatutCalculRest.builder() .statut(StatutCalculRest.StatutEnum.TERMINE) @@ -83,6 +89,10 @@ class StatutPourCalculPortImplTest { .nbEnCours(0) .nbTraite(100) .build()) + .operationNonIT(VolumeRest.builder() + .nbEnCours(0) + .nbTraite(100) + .build()) .messagerie(VolumeRest.builder() .nbEnCours(0) .nbTraite(5000) @@ -97,7 +107,7 @@ class StatutPourCalculPortImplTest { @Test void testStatutDesCalculs_NotFound() { var volume0 = new Volume(0L, 0L); - assertThrows(NotFoundException.class, () -> statutPourCalculPort.statutCalculs(volume0, volume0)); + assertThrows(NotFoundException.class, () -> statutPourCalculPort.statutCalculs(volume0, volume0, volume0)); } } diff --git a/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/controller/ImportCSVControllerTest.java b/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/controller/ImportCSVControllerTest.java index a38ae6109bbf325cdd1341d3d9851d02db9489c5..318f3eed3c261476354402674ae88e51b0d4d465 100644 --- a/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/controller/ImportCSVControllerTest.java +++ b/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/controller/ImportCSVControllerTest.java @@ -59,7 +59,7 @@ class ImportCSVControllerTest { @Test void importCSV_onNullFiles_shouldThrowResponseStatusExceptionWithBadRequest() { - var exception = assertThrows(ResponseStatusException.class, () -> importCSVController.importInterneCSV("nomLot", "2023-01-01", "TEST", null, null, null, null, null, null)); + var exception = assertThrows(ResponseStatusException.class, () -> importCSVController.importInterneCSV("nomLot", "2023-01-01", "TEST", null, null, null, null, null, null, null)); assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); assertEquals("Tous les fichiers ne peuvent être vides en même temps", exception.getReason()); @@ -71,10 +71,11 @@ class ImportCSVControllerTest { MockMultipartFile csvEquipements = new MockMultipartFile("csvEquipementsVide.csv", new byte[]{}); MockMultipartFile csvEquipementsVirtuels = new MockMultipartFile("csvEquipementVirtuelVide.csv", new byte[]{}); MockMultipartFile csvApplications = new MockMultipartFile("csvApplicationVide.csv", new byte[]{}); + MockMultipartFile csvOperationsNonIT = new MockMultipartFile("csvOperationsNonITVide.csv", new byte[]{}); MockMultipartFile csvMessagerie = new MockMultipartFile("csvMessagerieVide.csv", new byte[]{}); MockMultipartFile csvEntite = new MockMultipartFile("csvEntiteVide.csv", new byte[]{}); - var exception = assertThrows(ResponseStatusException.class, () -> importCSVController.importInterneCSV("nomLot", "2023-01-01", "TEST", csvDataCenters, csvEquipements, csvEquipementsVirtuels, csvApplications, csvMessagerie, csvEntite)); + var exception = assertThrows(ResponseStatusException.class, () -> importCSVController.importInterneCSV("nomLot", "2023-01-01", "TEST", csvDataCenters, csvEquipements, csvEquipementsVirtuels, csvApplications, csvOperationsNonIT, csvMessagerie, csvEntite)); assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); assertEquals("Tous les fichiers ne peuvent être vides en même temps", exception.getReason()); @@ -88,10 +89,11 @@ class ImportCSVControllerTest { MockMultipartFile csvEquipements = new MockMultipartFile("csvEquipementEquipementNonVide.csv", fileEquipement); MockMultipartFile csvEquipementsVirtuels = null; MockMultipartFile csvApplications = null; + MockMultipartFile csvOperationsNonIT = null; MockMultipartFile csvMessagerie = null; MockMultipartFile csvEntite = null; - var exception = assertThrows(ResponseStatusException.class, () -> importCSVController.importInterneCSV("TEST", nomLot, "2023-01-01", csvDataCenters, csvEquipements, csvEquipementsVirtuels, csvApplications, csvMessagerie, csvEntite)); + var exception = assertThrows(ResponseStatusException.class, () -> importCSVController.importInterneCSV("TEST", nomLot, "2023-01-01", csvDataCenters, csvEquipements, csvEquipementsVirtuels, csvApplications, csvOperationsNonIT, csvMessagerie, csvEntite)); assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); assertEquals("Le nom du Lot ne peut être pas vide", exception.getReason()); @@ -104,10 +106,11 @@ class ImportCSVControllerTest { MockMultipartFile csvEquipements = new MockMultipartFile("csvEquipementEquipementNonVide.csv", fileEquipement); MockMultipartFile csvEquipementsVirtuels = null; MockMultipartFile csvApplications = null; + MockMultipartFile csvoperationNonIT = null; MockMultipartFile csvMessagerie = null; MockMultipartFile csvEntite = null; - var exception = assertThrows(ResponseStatusException.class, () -> importCSVController.importInterneCSV("test", "20230101", "TEST", csvDataCenters, csvEquipements, csvEquipementsVirtuels, csvApplications, csvMessagerie, csvEntite)); + var exception = assertThrows(ResponseStatusException.class, () -> importCSVController.importInterneCSV("test", "20230101", "TEST", csvDataCenters, csvEquipements, csvEquipementsVirtuels, csvApplications, csvoperationNonIT, csvMessagerie, csvEntite)); assertEquals(HttpStatus.BAD_REQUEST, exception.getStatusCode()); assertEquals("La date du lot doit avoir le format yyyy-MM-dd", exception.getReason()); diff --git a/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/adapter/OperationNonITJpaAdapterTest.java b/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/adapter/OperationNonITJpaAdapterTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d53b9b73f25732a43271454b0d8d425084680a1c --- /dev/null +++ b/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/jpa/adapter/OperationNonITJpaAdapterTest.java @@ -0,0 +1,66 @@ +package org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.adapter; + +import org.instancio.Instancio; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mte.numecoeval.expositiondonneesentrees.domain.model.OperationNonIT; +import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.entity.OperationNonITEntity; +import org.mte.numecoeval.expositiondonneesentrees.infrastructure.jpa.repository.OperationNonITRepository; +import org.mte.numecoeval.expositiondonneesentrees.infrastructure.mapper.EntreeEntityMapper; +import org.mte.numecoeval.expositiondonneesentrees.infrastructure.mapper.EntreeEntityMapperImpl; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.Mockito.times; + +@ExtendWith(MockitoExtension.class) +class OperationNonITJpaAdapterTest { + @InjectMocks + private OperationNonITJpaAdapter jpaAdapter; + @Mock + OperationNonITRepository repository; + + EntreeEntityMapper entreeEntityMapper = new EntreeEntityMapperImpl(); + + @BeforeEach + void setup() { + jpaAdapter = new OperationNonITJpaAdapter(repository, entreeEntityMapper); + } + + @Test + void saveShouldConvertAndCallSave() { + OperationNonIT domain = Instancio.of(OperationNonIT.class).create(); + ArgumentCaptor<OperationNonITEntity> valueCapture = ArgumentCaptor.forClass(OperationNonITEntity.class); + + jpaAdapter.save(domain); + + Mockito.verify(repository, times(1)).save(valueCapture.capture()); + assertNotNull(valueCapture.getValue()); + } + + @Test + void saveAllShouldConvertAndCallSaveAll() { + OperationNonIT domain1 = Instancio.of(OperationNonIT.class).create(); + OperationNonIT domain2 = Instancio.of(OperationNonIT.class).create(); + ArgumentCaptor<List<OperationNonITEntity>> valueCapture = ArgumentCaptor.forClass(List.class); + List<OperationNonIT> entrees = Arrays.asList( + domain1, + domain2 + ); + + jpaAdapter.saveAll(entrees); + + Mockito.verify(repository, times(1)).saveAll(valueCapture.capture()); + assertNotNull(valueCapture.getValue()); + assertEquals(2, valueCapture.getValue().size()); + } +} diff --git a/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/DefaultValueServiceTest.java b/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/DefaultValueServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..71e0a0470bca9620e5dfe2f610da912d103eb62c --- /dev/null +++ b/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/DefaultValueServiceTest.java @@ -0,0 +1,63 @@ +package org.mte.numecoeval.expositiondonneesentrees.infrastructure.service; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mte.numecoeval.expositiondonneesentrees.domain.model.EquipementPhysique; + +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +@ExtendWith(MockitoExtension.class) +public class DefaultValueServiceTest { + @InjectMocks + DefaultValueService defaultValueService; + private String mode = "COPE"; + + @BeforeEach + public void init() { + List<String> modeUtilisationList = List.of(mode); + defaultValueService = new DefaultValueService(modeUtilisationList); + } + + public EquipementPhysique equipementPhysique() { + return EquipementPhysique.builder().build(); + } + + @Test + void importEqPhysique_with_TauxUtilisationBiggerThan1_shouldBeReplacedByNull() { + EquipementPhysique eq1 = equipementPhysique(); + eq1.setTauxUtilisation(21.0); + defaultValueService.setEquipementValeurDefaut(eq1); + assertNull(eq1.getTauxUtilisation()); + } + + @Test + void importEqPhysique_with_TauxUtilisationOK_shouldReturnSameTaux() { + EquipementPhysique eq1 = equipementPhysique(); + double tauxOK = 0.74; + eq1.setTauxUtilisation(tauxOK); + defaultValueService.setEquipementValeurDefaut(eq1); + assertEquals(tauxOK, eq1.getTauxUtilisation(), 0.01); + } + + @Test + void importEqPhysique_with_ModeUtilisationKO_shouldBeReplacedByNull() { + EquipementPhysique eq1 = equipementPhysique(); + eq1.setModeUtilisation("MODE_INCONNU"); + defaultValueService.setEquipementValeurDefaut(eq1); + assertNull(eq1.getModeUtilisation()); + } + + @Test + void importEqPhysique_with_ModeUtilisationOK_shouldReturnSameMode() { + EquipementPhysique eq1 = equipementPhysique(); + eq1.setModeUtilisation(mode); + defaultValueService.setEquipementValeurDefaut(eq1); + assertEquals(mode, eq1.getModeUtilisation()); + } +} diff --git a/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/ErrorManagementServiceTest.java b/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/ErrorManagementServiceTest.java index 0e4adc46067632e80213c44e6c6ee6bb155b6e2b..7f3d0c3fed86e0c14109f9e299091d19d1ca4bfd 100644 --- a/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/ErrorManagementServiceTest.java +++ b/services/api-expositiondonneesentrees/src/test/java/org/mte/numecoeval/expositiondonneesentrees/infrastructure/service/ErrorManagementServiceTest.java @@ -1,5 +1,10 @@ package org.mte.numecoeval.expositiondonneesentrees.infrastructure.service; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.apache.commons.lang3.tuple.Pair; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -8,49 +13,44 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import org.mte.numecoeval.expositiondonneesentrees.domain.model.EquipementPhysique; +import org.mte.numecoeval.expositiondonneesentrees.domain.model.OperationNonIT; import org.mte.numecoeval.expositiondonneesentrees.domain.ports.output.ReferentielServicePort; import org.mte.numecoeval.expositiondonneesentrees.infrastructure.config.MessageProperties; +import org.mte.numecoeval.expositiondonneesentrees.referentiels.generated.api.model.CritereDTO; +import org.mte.numecoeval.expositiondonneesentrees.referentiels.generated.api.model.EtapeDTO; +import org.mte.numecoeval.expositiondonneesentrees.referentiels.generated.api.model.FacteurCaracterisationDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; import java.io.IOException; import java.time.LocalDate; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Arrays; import java.util.List; -import java.util.Map; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; -@ExtendWith(MockitoExtension.class) +@ExtendWith({MockitoExtension.class, SpringExtension.class}) +@ContextConfiguration(initializers = ConfigDataApplicationContextInitializer.class) +@EnableConfigurationProperties(value = MessageProperties.class) public class ErrorManagementServiceTest { - @Mock + private static final ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule()); + + @Autowired MessageProperties messageProperties; @InjectMocks ErrorManagementService errorManagementService; @Mock ReferentielServicePort referentielServicePort; - private Map<String, String> messages = new HashMap<>(); - @BeforeEach public void init() { - List<String> modeUtilisationList = new ArrayList<>(); - errorManagementService = new ErrorManagementService(messageProperties, referentielServicePort, modeUtilisationList); - messages.put("LIGNE_INCONSISTENTE", "Fichier %s , La ligne n°%d n'est pas consistente avec les headers du fichier"); - messages.put("LIGNE_INCORRECTE", "Fichier %s , La ligne n°%d est incorrecte pour l'objet %s requise"); - messages.put("TYPE_EQUIPEMENT_INCONNU", "Le type d'équipement %s correspondant à l'équipement %s n'existe pas dans la table des références ref_TypeEquipement"); - messages.put("EQUIPEMENT_MIX_ELEC_LOCALISATION_INCONNUE", "Le pays %s correspondant à l'équipement physique %s n'existe pas dans la table des mix électriques ref_MixElec.pays"); - messages.put("DATACENTER_MIX_ELEC_LOCALISATION_INCONNUE", "La localisation %s du centre de données %s n'existe pas dans la table des mix électriques ref_MixElec.pays"); - messages.put("EQUIPEMENT_CORRESPONDANCE_INCONNUE", "L'équipement %s de type %s ne possède pas de référence d'équipement par défaut dans la table ref_typeEquipement et pas de correspondance dans la table ref_CorrespondanceRefEqP"); - messages.put("EQUIPEMENT_IMPACT_INCONNU", "L'impact de l'équipement de référence %s pour l'étape %s et le critère %s ne pourra pas être calculé en raison de l'absence de facteur d'impact sur l'équipement"); - messages.put("EQUIPEMENT_DATE_INCOHERENTE", "L'âge de l'équipement %s ne peut être calculé car sa date de retrait précède sa date d'achat"); - messages.put("EQUIPEMENT_MODE_UTILISATION_INCONNU", "Le mode d'utilisation renseigné '%s' est inconnu du référentiel"); - messages.put("EQUIPEMENT_TAUX_UTILISATION_INVALIDE", "Le taux d'utilisation renseigné '%s' n'est pas valide, il doit être compris entre 0 et 1, le taux par défaut sera appliqué."); - messages.put("EQUIPEMENT_DATACENTER_INCONNU", "L'équipement %s n'est lié à aucun datacenter"); - messages.put("EQUIPEMENT_VIRTUEL_INCONNU", "L'équipement virtuel %s n'est supporté par aucun équipement physique"); - messages.put("APPLICATION_AVEC_EQUIPEMENT_PHYSIQUE_INCONNU", "L'application %s n'est supporté par aucun équipement physique"); - messages.put("APPLICATION_AVEC_EQUIPEMENT_VIRTUEL_INCONNU", "L'application %s n'est supporté par aucun équipement virtuel"); - Mockito.lenient().when(messageProperties.getMessages()).thenReturn(messages); + errorManagementService = new ErrorManagementService(messageProperties, referentielServicePort, new ArrayList<>()); } @Test @@ -67,11 +67,11 @@ public class ErrorManagementServiceTest { .modeUtilisation("COPE").build(); var actual = errorManagementService.checkEquipementPhysique(eq1, ""); - assertTrue(actual.getKey().stream().anyMatch(ds -> "L'âge de l'équipement physical-eq-001 ne peut être calculé car sa date de retrait précède sa date d'achat".equals(ds))); + Assertions.assertTrue(actual.getKey().stream().anyMatch("L'âge de l'équipement physical-eq-001 ne peut être calculé car sa date de retrait précède sa date d'achat"::equals)); } @Test - void importEqPhysique_with_DateEntreeAfterDateRetrait_shouldNotReturnReportWith1Error() throws IOException { + void importEqPhysique_with_DateEntreeBeforeDateRetrait_shouldNotReturnReportWith1Error() throws IOException { EquipementPhysique eq1 = EquipementPhysique.builder() .nomEquipementPhysique("physical-eq-001") .modele("P2719") @@ -84,6 +84,189 @@ public class ErrorManagementServiceTest { .modeUtilisation("COPE").build(); var actual = errorManagementService.checkEquipementPhysique(eq1, ""); - assertFalse(actual.getKey().stream().anyMatch(ds -> "L'âge de l'équipement physical-eq-001 ne peut être calculé car sa date de retrait précède sa date d'achat".equals(ds))); + Assertions.assertFalse(actual.getKey().stream().anyMatch("L'âge de l'équipement physical-eq-001 ne peut être calculé car sa date de retrait précède sa date d'achat"::equals)); + } + + @Test + void importEqPhysique_with_DureeUsageInterneNegative_shouldReturnReportWith1Error() throws IOException { + EquipementPhysique eq1 = EquipementPhysique.builder() + .nomEquipementPhysique("physical-eq-001") + .quantite(1.0) + .dureeUsageInterne(-3.6) + .type("Monitor") + .statut("In use") + .paysDUtilisation("France") + .build(); + + var actual = errorManagementService.checkEquipementPhysique(eq1, ""); + assertTrue(actual.getKey().stream().anyMatch(ds -> "La durée d'usage interne de l'équipement physical-eq-001 est négative ou nulle donc invalide".equals(ds))); + } + + @Test + void importEqPhysique_with_DureeUsageInterneZero_shouldReturnReportWith1Error() throws IOException { + EquipementPhysique eq1 = EquipementPhysique.builder() + .nomEquipementPhysique("physical-eq-001") + .quantite(1.0) + .dureeUsageInterne(0.0) + .type("Monitor") + .statut("In use") + .paysDUtilisation("France") + .build(); + + var actual = errorManagementService.checkEquipementPhysique(eq1, ""); + assertTrue(actual.getKey().stream().anyMatch(ds -> "La durée d'usage interne de l'équipement physical-eq-001 est négative ou nulle donc invalide".equals(ds))); + } + + @Test + void importEqPhysique_with_DureeUsageInternePositive_shouldNotReturnReportWith1Error() throws IOException { + EquipementPhysique eq1 = EquipementPhysique.builder() + .nomEquipementPhysique("physical-eq-001") + .quantite(1.0) + .dureeUsageInterne(3.6) + .type("Monitor") + .statut("In use") + .paysDUtilisation("France") + .build(); + + var actual = errorManagementService.checkEquipementPhysique(eq1, ""); + assertFalse(actual.getKey().stream().anyMatch(ds -> "La durée d'usage interne de l'équipement physical-eq-001 est négative ou nulle donc invalide".equals(ds))); + } + + @Test + void importEqPhysique_with_DureeUsageAvalNegative_shouldReturnReportWith1Error() throws IOException { + EquipementPhysique eq1 = EquipementPhysique.builder() + .nomEquipementPhysique("physical-eq-001") + .quantite(1.0) + .dureeUsageInterne(1.0) + .dureeUsageAval(-1.0) + .type("Monitor") + .statut("In use") + .paysDUtilisation("France") + .build(); + + var actual = errorManagementService.checkEquipementPhysique(eq1, ""); + assertTrue(actual.getKey().stream().anyMatch(ds -> "La durée d'usage aval de l'équipement physical-eq-001 est négative donc invalide".equals(ds))); + } + + @Test + void importEqPhysique_with_DureeUsageAvalZero_shouldNotReturnReportWith1Error() throws IOException { + EquipementPhysique eq1 = EquipementPhysique.builder() + .nomEquipementPhysique("physical-eq-001") + .quantite(1.0) + .dureeUsageInterne(1.0) + .dureeUsageAval(0.0) + .type("Monitor") + .statut("In use") + .paysDUtilisation("France") + .build(); + + var actual = errorManagementService.checkEquipementPhysique(eq1, ""); + assertFalse(actual.getKey().stream().anyMatch(ds -> "La durée d'usage aval de l'équipement physical-eq-001 est négative donc invalide".equals(ds))); + } + + @Test + void importOperationNonIT_with_TypeNotInRefType_shouldReturnReportWith1Error() { + OperationNonIT eq1 = OperationNonIT.builder() + .nomItemNonIT("Batiment_datacenter_St_Malo") + .quantite(1.0) + .dureeDeVie(5.0) + .type("Monitor") + .localisation("France").build(); + var actual = errorManagementService.checkOperationNonIT(eq1, null); + Assertions.assertEquals("L'item Batiment_datacenter_St_Malo de type Monitor ne possède pas de référence d'item par défaut dans la table ref_type_item", actual.getKey().get(0)); + + } + + @Test + void importOperationNonIT_with_TypeNotRefTypeItem_shouldReturnReportWith1Error() throws JsonProcessingException { + OperationNonIT eq1 = OperationNonIT.builder() + .nomItemNonIT("Batiment_datacenter_St_Malo") + .quantite(1.0) + .dureeDeVie(5.0) + .type("batiment") + .localisation("France").build(); + + /* MOCK REFERENTIEL : FacteurCaracterisation */ + Mockito.lenient().when(referentielServicePort.getFacteurCaracterisation(any(), any(), any())).thenReturn(null); + + /* MOCK REFERENTIEL : Etapes */ + Mockito.lenient().when(referentielServicePort.getAllEtapes()).thenReturn(Arrays.asList(mapper.readValue(""" + [{ "code": "UTILISATION", "libelle": "Using" }] + """, EtapeDTO[].class))); + + /* MOCK REFERENTIEL : Criteres */ + Mockito.lenient().when(referentielServicePort.getAllCriteres()).thenReturn(Arrays.asList(mapper.readValue(""" + [{ + "nomCritere": "Climate change", + "unite": "kg CO2 eq", + "description": "Greenhouse gases (GHG)" + }] + """, CritereDTO[].class))); + var actual = errorManagementService.checkOperationNonIT(eq1, eq1.getType()); + Assertions.assertEquals("L'impact de l'item de référence batiment pour l'étape UTILISATION et le critère Climate change ne pourra pas être calculé en raison de l'absence de facteur d'impact sur cet item", actual.getValue().get(0)); + } + + @Test + void importOperationNonIT_with_TypeInRefTypeItem_shouldNotReturnError() throws JsonProcessingException { + OperationNonIT eq1 = OperationNonIT.builder() + .nomItemNonIT("Batiment_datacenter_St_Malo") + .quantite(1.0) + .dureeDeVie(5.0) + .type("batiment") + .localisation("France").build(); + + /* MOCK REFERENTIEL : FacteurCaracterisation */ + Mockito.lenient().when(referentielServicePort.getFacteurCaracterisation(any(), any(), any())).thenReturn(mapper.readValue(""" + { + "nom": "reseau-fixe-1", + "etape" : "UTILISATION", + "critere" : "Climate change", + "localisation": "France", + "consoElecMoyenne": 12.7, + "valeur" : "8.34" + } + """, FacteurCaracterisationDTO.class)); + + /* MOCK REFERENTIEL : Etapes */ + Mockito.lenient().when(referentielServicePort.getAllEtapes()).thenReturn(Arrays.asList(mapper.readValue(""" + [{ "code": "UTILISATION", "libelle": "Using" }] + """, EtapeDTO[].class))); + + /* MOCK REFERENTIEL : Criteres */ + Mockito.lenient().when(referentielServicePort.getAllCriteres()).thenReturn(Arrays.asList(mapper.readValue(""" + [{ + "nomCritere": "Climate change", + "unite": "kg CO2 eq", + "description": "Greenhouse gases (GHG)" + }] + """, CritereDTO[].class))); + Pair<List<String>, List<String>> actual = errorManagementService.checkOperationNonIT(eq1, eq1.getType()); + Assertions.assertEquals(0, actual.getKey().size()); + } + + @Test + void importDataCenter_with_QualiteGoodValue_shouldWork() { + Assertions.assertNull(errorManagementService.checkQualiteDonnees("BASSE", "L'équipement physique", "eq1")); + } + + @Test + void importDataCenter_with_QualiteNull_shouldNotReportWarning() { + Assertions.assertNull(errorManagementService.checkQualiteDonnees(null, "L'équipement physique", "eq1")); + } + + @Test + void importDataCenter_with_QualiteWrongValue_shouldReturnReportWith1Warning() { + Assertions.assertEquals( + "L'équipement physique 'eq1' possède une valeur de qualité invalide renseignée. La valeur 'SUPER BASSE' est ignorée car elle n'est pas l'une de ces valeurs: BASSE, MOYENNE, HAUTE", + errorManagementService.checkQualiteDonnees("SUPER BASSE", "L'équipement physique", "eq1") + ); + } + + @Test + void importEqPhysique_with_NomTypeInvalide() { + Assertions.assertEquals( + "L'équipement physique 'eq1' possède un type dont la valeur : 'Monitor/' est invalide. La valeur ne doit pas contenir les caractères '/' et '\\'.", + errorManagementService.checkNomTypeItem("Monitor/", "L'équipement physique", "eq1") + ); } } diff --git a/services/api-referentiel/pom.xml b/services/api-referentiel/pom.xml index e434f78f5f15e35a581fa84eea05483567980bda..7850b698342ff700a371a131bc4c39ef08cfece0 100644 --- a/services/api-referentiel/pom.xml +++ b/services/api-referentiel/pom.xml @@ -5,12 +5,12 @@ <parent> <groupId>org.mte.numecoeval</groupId> <artifactId>core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <artifactId>api-referentiel</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> <name>api-referentiel</name> <description>API Referentiel - Lecture, chargement et exposition par API</description> diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/model/Hypothese.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/model/Hypothese.java index 1c55577c9ee2320a50ceed50ed7ffac765ad3c15..a1248c8efa5f5d142e89b60b449fc5b95a707494 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/model/Hypothese.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/model/Hypothese.java @@ -1,10 +1,6 @@ package org.mte.numecoeval.referentiel.domain.model; -import lombok.AccessLevel; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; +import lombok.*; import lombok.experimental.Accessors; import lombok.experimental.FieldDefaults; @@ -18,5 +14,6 @@ public class Hypothese implements AbstractReferentiel { String code; String valeur; String source; + String description; } diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/model/TypeItem.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/model/TypeItem.java new file mode 100644 index 0000000000000000000000000000000000000000..363366091d269083926b4fd1e6f5a7bc628605f0 --- /dev/null +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/model/TypeItem.java @@ -0,0 +1,22 @@ +package org.mte.numecoeval.referentiel.domain.model; + +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Data; +import lombok.experimental.FieldDefaults; + +@Builder +@Data +@FieldDefaults(level = AccessLevel.PRIVATE) +public class TypeItem implements AbstractReferentiel { + String type; + String categorie; + boolean serveur; + String commentaire; + Double dureeVieDefaut; + String refHypothese; + String source; + // Référence de l'item par défaut, permet des correspondances en cas d'absence de correspondance directe. + String refItemParDefaut; + +} diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/ports/input/impl/ImportHypothesePortImpl.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/ports/input/impl/ImportHypothesePortImpl.java index a14c212bf109b37daa8441740e7cf7c1e9d937e8..925ad02f229a0a897d473fccff3a5919fff08d85 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/ports/input/impl/ImportHypothesePortImpl.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/ports/input/impl/ImportHypothesePortImpl.java @@ -3,10 +3,10 @@ package org.mte.numecoeval.referentiel.domain.ports.input.impl; import lombok.extern.slf4j.Slf4j; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVRecord; -import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.HypotheseDTO; import org.mte.numecoeval.referentiel.domain.data.ResultatImport; import org.mte.numecoeval.referentiel.domain.exception.ReferentielException; import org.mte.numecoeval.referentiel.domain.ports.input.ImportCSVReferentielPort; +import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.HypotheseDTO; import java.io.InputStream; import java.io.InputStreamReader; @@ -18,14 +18,16 @@ import java.util.List; @Slf4j public class ImportHypothesePortImpl implements ImportCSVReferentielPort<HypotheseDTO> { private static final String HEADER_VALEUR = "valeur"; - private static final String[] HEADERS = new String[]{"cle", HEADER_VALEUR, "source"}; + private static final String[] MANDATORY_HEADERS = new String[]{"cle", HEADER_VALEUR, "source"}; + + private static final String[] HEADERS = new String[]{"cle", HEADER_VALEUR, "source", "description"}; public static String[] getHeaders() { return HEADERS; } public void checkCSVRecord(CSVRecord csvRecord) throws ReferentielException { - checkAllHeadersAreMapped(csvRecord, HEADERS); + checkAllHeadersAreMapped(csvRecord, MANDATORY_HEADERS); checkFieldIsMappedAndNotBlankInCSVRecord(csvRecord, "cle"); checkFieldIsMappedAndNotBlankInCSVRecord(csvRecord, HEADER_VALEUR); } @@ -50,11 +52,11 @@ public class ImportHypothesePortImpl implements ImportCSVReferentielPort<Hypothe .valeur(csvRecord.get(HEADER_VALEUR).trim()) .code(csvRecord.get("cle").trim()) .source(csvRecord.get("source").trim()) + .description(getStringValueFromRecord(csvRecord, "description")) .build()); - } - catch (Exception e) { - log.error("Erreur prévue lors de la lecture de la ligne {} : {}", csvRecord.getRecordNumber()+1, e.getMessage()); - resultatImport.getErreurs().add( e.getMessage() ); + } catch (Exception e) { + log.error("Erreur prévue lors de la lecture de la ligne {} : {}", csvRecord.getRecordNumber() + 1, e.getMessage()); + resultatImport.getErreurs().add(e.getMessage()); } }); diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/ports/input/impl/ImportTypeItemPortImpl.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/ports/input/impl/ImportTypeItemPortImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..73182924f3cb27779e65767de59845065f55ab0d --- /dev/null +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/ports/input/impl/ImportTypeItemPortImpl.java @@ -0,0 +1,78 @@ +package org.mte.numecoeval.referentiel.domain.ports.input.impl; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVRecord; +import org.apache.commons.lang3.BooleanUtils; +import org.mte.numecoeval.referentiel.domain.data.ResultatImport; +import org.mte.numecoeval.referentiel.domain.exception.ReferentielException; +import org.mte.numecoeval.referentiel.domain.ports.input.ImportCSVReferentielPort; +import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.TypeItemDTO; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@Slf4j +public class ImportTypeItemPortImpl implements ImportCSVReferentielPort<TypeItemDTO> { + private static final String HEADER_TYPE = "type"; + private static final String[] HEADERS = new String[]{HEADER_TYPE, "categorie", "serveur", "commentaire", "dureeVieDefaut", "refHypothese", "source", "refItemParDefaut"}; + + public static String[] getHeaders() { + return HEADERS; + } + + public void checkCSVRecord(CSVRecord csvRecord) throws ReferentielException { + checkAllHeadersAreMapped(csvRecord, HEADERS); + checkFieldIsMappedAndNotBlankInCSVRecord(csvRecord, HEADER_TYPE); + } + + @Override + public ResultatImport<TypeItemDTO> importCSV(InputStream csvInputStream) { + ResultatImport<TypeItemDTO> resultatImport = new ResultatImport<>(); + List<TypeItemDTO> dtos = new ArrayList<>(); + + try (Reader reader = new InputStreamReader(csvInputStream)) { + Iterable<CSVRecord> records = CSVFormat.DEFAULT.builder() + .setHeader() + .setDelimiter(CSV_SEPARATOR) + .setTrim(true) + .setAllowMissingColumnNames(true) + .setSkipHeaderRecord(true) + .build().parse(reader); + records.forEach(csvRecord -> { + try { + checkCSVRecord(csvRecord); + dtos.add(TypeItemDTO.builder() + .type(csvRecord.get(HEADER_TYPE).trim()) + .categorie(csvRecord.get("categorie").trim()) + .serveur(BooleanUtils.toBoolean(csvRecord.get("serveur").trim())) + .commentaire(csvRecord.get("commentaire").trim()) + .dureeVieDefaut(getDoubleValueFromRecord(csvRecord, "dureeVieDefaut", null)) + .refHypothese(csvRecord.get("refHypothese").trim()) + .source(csvRecord.get("source").trim()) + .refItemParDefaut(getStringValueFromRecord(csvRecord, "refItemParDefaut")) + .build()); + } catch (Exception e) { + log.error("Erreur prévue lors de la lecture de la ligne {} : {}", csvRecord.getRecordNumber() + 1, e.getMessage()); + resultatImport.getErreurs().add(e.getMessage()); + } + }); + + } catch (Exception e) { + log.error("Erreur de traitement du fichier", e); + + resultatImport.setErreurs(Collections.singletonList("Le fichier CSV n'a pas pu être lu.")); + resultatImport.setNbrLignesImportees(0); + resultatImport.setObjects(null); + return resultatImport; + } + resultatImport.setObjects(dtos); + resultatImport.setNbrLignesImportees(dtos.size()); + return resultatImport; + } + +} diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/ports/output/ReferentielPersistencePort.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/ports/output/ReferentielPersistencePort.java index 8ea16327109dcd0edaa87801de08a740f88876b9..78061eaf1ff653614d3459b23294a5bafc30f95f 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/ports/output/ReferentielPersistencePort.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/domain/ports/output/ReferentielPersistencePort.java @@ -45,5 +45,14 @@ public interface ReferentielPersistencePort<T extends AbstractReferentiel, P ext */ List<T> getAll(); + /** + * Find by filters + * + * @param params param list + * @return the list of objects + */ + default List<T> findByFilters(String... params) throws ReferentielException { + return List.of(); + } } diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/HypotheseCsvExportService.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/HypotheseCsvExportService.java index 684802434814496fe3fb183ca27a8dd6f785e7af..e5a44db7d86b9daf4dced6adf94b789059357397 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/HypotheseCsvExportService.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/HypotheseCsvExportService.java @@ -37,7 +37,7 @@ public class HypotheseCsvExportService extends ReferentielCsvExportService<Hypot @Override public void printRecord(CSVPrinter csvPrinter, HypotheseEntity objectToWrite) throws IOException { - csvPrinter.printRecord(objectToWrite.getCode(),objectToWrite.getValeur(),objectToWrite.getSource()); + csvPrinter.printRecord(objectToWrite.getCode(), objectToWrite.getValeur(), objectToWrite.getSource(), objectToWrite.getDescription()); } } diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/TypeEquipementCsvExportService.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/TypeEquipementCsvExportService.java index adee3de7ce6a40528edc120eac8b4420da7c6b52..51bcb9f0d24813cd5917fbf28ecd293aba7866ff 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/TypeEquipementCsvExportService.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/TypeEquipementCsvExportService.java @@ -1,23 +1,33 @@ package org.mte.numecoeval.referentiel.infrastructure.adapter.export; import org.apache.commons.csv.CSVPrinter; +import org.mte.numecoeval.referentiel.domain.model.TypeEquipement; +import org.mte.numecoeval.referentiel.domain.model.TypeItem; import org.mte.numecoeval.referentiel.domain.ports.input.impl.ImportTypeEquipementPortImpl; import org.mte.numecoeval.referentiel.domain.ports.output.ReferentielCsvExportService; -import org.mte.numecoeval.referentiel.infrastructure.jpa.entity.TypeEquipementEntity; -import org.mte.numecoeval.referentiel.infrastructure.jpa.repository.TypeEquipementRepository; +import org.mte.numecoeval.referentiel.infrastructure.jpa.repository.TypeItemRepository; +import org.mte.numecoeval.referentiel.infrastructure.mapper.TypeEquipementMapper; +import org.mte.numecoeval.referentiel.infrastructure.mapper.TypeItemMapper; import org.springframework.stereotype.Service; import java.io.IOException; import java.util.List; +import static org.mte.numecoeval.referentiel.utils.Constants.CATEGORIE_EQUIPEMENT_PHYSIQUE; + @Service -public class TypeEquipementCsvExportService extends ReferentielCsvExportService<TypeEquipementEntity> { +public class TypeEquipementCsvExportService extends ReferentielCsvExportService<TypeEquipement> { + + private final TypeItemRepository repository; + private final TypeItemMapper typeItemMapper; + private final TypeEquipementMapper typeEquipementMapper; - private final TypeEquipementRepository repository; - public TypeEquipementCsvExportService(TypeEquipementRepository repository) { - super(TypeEquipementEntity.class); + public TypeEquipementCsvExportService(TypeItemRepository repository, TypeItemMapper typeItemMapper, TypeEquipementMapper typeEquipementMapper) { + super(TypeEquipement.class); this.repository = repository; + this.typeItemMapper = typeItemMapper; + this.typeEquipementMapper = typeEquipementMapper; } @Override @@ -26,17 +36,18 @@ public class TypeEquipementCsvExportService extends ReferentielCsvExportService< } @Override - public List<TypeEquipementEntity> getObjectsToWrite() { - return repository.findAll(); + public List<TypeEquipement> getObjectsToWrite() { + List<TypeItem> typeItemList = typeItemMapper.toDomains(repository.findByCategorie(CATEGORIE_EQUIPEMENT_PHYSIQUE)); + return typeEquipementMapper.toTypeEquipements(typeItemList); } @Override - protected String getObjectId(TypeEquipementEntity object) { + protected String getObjectId(TypeEquipement object) { return object.getType(); } @Override - public void printRecord(CSVPrinter csvPrinter, TypeEquipementEntity objectToWrite) throws IOException { + public void printRecord(CSVPrinter csvPrinter, TypeEquipement objectToWrite) throws IOException { csvPrinter.printRecord(objectToWrite.getType(), objectToWrite.isServeur(), objectToWrite.getCommentaire(), diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/TypeItemCsvExportService.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/TypeItemCsvExportService.java new file mode 100644 index 0000000000000000000000000000000000000000..851bba7b29e1f6cf504270b4fd76745036eef4e3 --- /dev/null +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/TypeItemCsvExportService.java @@ -0,0 +1,49 @@ +package org.mte.numecoeval.referentiel.infrastructure.adapter.export; + +import org.apache.commons.csv.CSVPrinter; +import org.mte.numecoeval.referentiel.domain.ports.input.impl.ImportTypeItemPortImpl; +import org.mte.numecoeval.referentiel.domain.ports.output.ReferentielCsvExportService; +import org.mte.numecoeval.referentiel.infrastructure.jpa.entity.TypeItemEntity; +import org.mte.numecoeval.referentiel.infrastructure.jpa.repository.TypeItemRepository; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.util.List; + +@Service +public class TypeItemCsvExportService extends ReferentielCsvExportService<TypeItemEntity> { + + private final TypeItemRepository repository; + + public TypeItemCsvExportService(TypeItemRepository repository) { + super(TypeItemEntity.class); + this.repository = repository; + } + + @Override + public String[] getHeaders() { + return ImportTypeItemPortImpl.getHeaders(); + } + + @Override + public List<TypeItemEntity> getObjectsToWrite() { + return repository.findAll(); + } + + @Override + protected String getObjectId(TypeItemEntity object) { + return object.getType(); + } + + @Override + public void printRecord(CSVPrinter csvPrinter, TypeItemEntity objectToWrite) throws IOException { + csvPrinter.printRecord(objectToWrite.getType(), + objectToWrite.getCategorie(), + objectToWrite.isServeur(), + objectToWrite.getCommentaire(), + formatDouble(objectToWrite.getDureeVieDefaut()), + objectToWrite.getRefHypothese(), + objectToWrite.getSource(), objectToWrite.getRefItemParDefaut()); + } + +} diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/init/MigrationToRefTypeItem.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/init/MigrationToRefTypeItem.java new file mode 100644 index 0000000000000000000000000000000000000000..a4f9a4cf9a8d3d132133aff76151dbc15ca2b04d --- /dev/null +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/init/MigrationToRefTypeItem.java @@ -0,0 +1,35 @@ +package org.mte.numecoeval.referentiel.infrastructure.init; + +import jakarta.annotation.PostConstruct; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.mte.numecoeval.referentiel.domain.exception.ReferentielException; +import org.mte.numecoeval.referentiel.infrastructure.jpa.adapter.TypeItemJpaAdapter; +import org.mte.numecoeval.referentiel.infrastructure.jpa.entity.TypeEquipementEntity; +import org.mte.numecoeval.referentiel.infrastructure.jpa.repository.TypeEquipementRepository; +import org.mte.numecoeval.referentiel.infrastructure.mapper.TypeEquipementMapper; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@Slf4j +@AllArgsConstructor +public class MigrationToRefTypeItem { + + private TypeEquipementRepository typeEquipementRepository; + private TypeEquipementMapper typeEquipementMapper; + private TypeItemJpaAdapter typeItemJpaAdapter; + + @PostConstruct + public void init() throws ReferentielException { + log.info("démarrage de la migration de la table ref_type_equipement vers ref_type_item"); + List<TypeEquipementEntity> typesEquipement = typeEquipementRepository.findAll(); + if (!typesEquipement.isEmpty()) { + log.info("migration des référentiels de types d'équipements existants vers la nouvelle table"); + typeItemJpaAdapter.saveAll(typeEquipementMapper.toTypesItem(typeEquipementMapper.toDomaines(typesEquipement))); + typeEquipementRepository.deleteAll(); + log.info("fin de la migration de la table ref_type_equipement vers ref_type_item"); + } + } +} diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/CorrespondanceRefEquipementJpaAdapter.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/CorrespondanceRefEquipementJpaAdapter.java index f57cd54eff759fa682146d885396b2bc09e70168..39b3a471cf91b174f075d3ff3fc4011b597d344d 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/CorrespondanceRefEquipementJpaAdapter.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/CorrespondanceRefEquipementJpaAdapter.java @@ -16,7 +16,7 @@ import java.util.List; @Service @Slf4j @AllArgsConstructor -public class CorrespondanceRefEquipementJpaAdapter implements ReferentielPersistencePort<CorrespondanceRefEquipement,String> { +public class CorrespondanceRefEquipementJpaAdapter implements ReferentielPersistencePort<CorrespondanceRefEquipement, String> { CorrespondanceRefEquipementMapper mapper; CorrespondanceRefEquipementRepository repository; @@ -24,7 +24,7 @@ public class CorrespondanceRefEquipementJpaAdapter implements ReferentielPersist @Override public CorrespondanceRefEquipement save(CorrespondanceRefEquipement referentiel) throws ReferentielException { var entityToSave = mapper.toEntity(referentiel); - if(entityToSave != null) { + if (entityToSave != null) { var entitySaved = repository.save(entityToSave); return mapper.toDomain(entitySaved); } @@ -41,11 +41,11 @@ public class CorrespondanceRefEquipementJpaAdapter implements ReferentielPersist @Override public CorrespondanceRefEquipement get(String id) throws ReferentielException { - if(id != null) { - var entityOpt= repository.findById(id); + if (id != null) { + var entityOpt = repository.findById(id); return entityOpt .map(entity -> mapper.toDomain(entity)) - .orElseThrow(() -> new ReferentielException("Correspondance au RefEquipement "+ id +" non trouvé")); + .orElseThrow(() -> new ReferentielException("Correspondance au RefEquipement " + id + " non trouvé")); } throw new ReferentielException("Correspondance au RefEquipement (id null) non trouvé"); } @@ -63,4 +63,5 @@ public class CorrespondanceRefEquipementJpaAdapter implements ReferentielPersist .map(typeEquipementEntity -> mapper.toDomain(typeEquipementEntity)) .toList(); } + } diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/EtapeJpaAdapter.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/EtapeJpaAdapter.java index f41082688aca9e14fffef4141d7132667ac5e51d..b1aadad62690147b79edb7fa4724c7a7e408a10b 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/EtapeJpaAdapter.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/EtapeJpaAdapter.java @@ -52,4 +52,5 @@ public class EtapeJpaAdapter implements ReferentielPersistencePort<Etape, EtapeI public List<Etape> getAll() { return etapeMapper.toDomains(etapeRepository.findAll()); } + } diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/FacteurCaracterisationJpaAdapter.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/FacteurCaracterisationJpaAdapter.java index a01d01daab7ca1dcdcf67e8fbaa58b8c62ce6d99..9456a4818963fbb5f9b16c7ec1a61bcb8b6b2257 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/FacteurCaracterisationJpaAdapter.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/FacteurCaracterisationJpaAdapter.java @@ -21,11 +21,11 @@ import java.util.Optional; @Slf4j @AllArgsConstructor public class FacteurCaracterisationJpaAdapter implements ReferentielPersistencePort<FacteurCaracterisation, FacteurCaracterisationId> { + private FacteurCaracterisationRepository repository; private FacteurCaracterisationMapper mapper; - @Override public FacteurCaracterisation save(FacteurCaracterisation referentiel) throws ReferentielException { var entityToSave = mapper.toEntity(referentiel); @@ -54,6 +54,14 @@ public class FacteurCaracterisationJpaAdapter implements ReferentielPersistenceP throw new ReferentielException("Facteur Caractérisation non trouvé"); } + @Override + public List<FacteurCaracterisation> findByFilters(String... params) throws ReferentielException { + List<FacteurCaracterisationEntity> facteurCaracterisationEntity = + repository.findByCritereAndEtapeAndNomAndLocalisationAndCategorie(params[0], params[1], params[2], params[3], params[4]); + + return mapper.toDomains(facteurCaracterisationEntity); + } + @Override public void purge() { repository.deleteAll(); diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/HypotheseJpaAdapter.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/HypotheseJpaAdapter.java index ec82b030e9eb5fea4709fbcdf3cc9ace87cc64dd..1ec8b369edcb46a712ad02b4b79efa2381b32529 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/HypotheseJpaAdapter.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/HypotheseJpaAdapter.java @@ -28,7 +28,7 @@ public class HypotheseJpaAdapter implements ReferentielPersistencePort<Hypothese @Override public Hypothese save(Hypothese referentiel) throws ReferentielException { var entityToSave = hypotheseMapper.toEntity(referentiel); - if(entityToSave != null) { + if (entityToSave != null) { var entitySaved = hypotheseRepository.save(entityToSave); return hypotheseMapper.toDomain(entitySaved); } diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/ImpactMessagerieJpaAdapter.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/ImpactMessagerieJpaAdapter.java index 585544e835c4e9608192d2ce99bb80cb90548d47..d6142962d8fa2e98d875c0600ab46b87082172fe 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/ImpactMessagerieJpaAdapter.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/ImpactMessagerieJpaAdapter.java @@ -17,7 +17,7 @@ import java.util.List; @Service @Slf4j @AllArgsConstructor -public class ImpactMessagerieJpaAdapter implements ReferentielPersistencePort<ImpactMessagerie,String> { +public class ImpactMessagerieJpaAdapter implements ReferentielPersistencePort<ImpactMessagerie, String> { ImpactMessagerieMapper impactMessagerieMapper; ImpactMessagerieRepository impactMessagerieRepository; @@ -36,8 +36,8 @@ public class ImpactMessagerieJpaAdapter implements ReferentielPersistencePort<Im @Override public ImpactMessagerie get(String critere) throws ReferentielException { - if(critere != null) { - var entityOpt= impactMessagerieRepository.findById(critere); + if (critere != null) { + var entityOpt = impactMessagerieRepository.findById(critere); return entityOpt .map(impactMessagerieEntity -> impactMessagerieMapper.toDomain(impactMessagerieEntity)) .orElseThrow(() -> new ReferentielException("ImpactMessagerie non trouvé")); diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/MixElectriqueJpaAdapter.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/MixElectriqueJpaAdapter.java index f1131a65b1bb1bace3fc2739ea948103d4d1e0ef..9916db201dedad228a31d95d283d0f851f369084 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/MixElectriqueJpaAdapter.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/MixElectriqueJpaAdapter.java @@ -16,7 +16,6 @@ import org.springframework.stereotype.Service; import java.util.Collection; import java.util.List; -import java.util.Optional; @Service @@ -51,9 +50,12 @@ public class MixElectriqueJpaAdapter implements ReferentielPersistencePort<MixEl public MixElectrique get(MixElectriqueId id) throws ReferentielException { if (id != null) { - Optional<FacteurCaracterisationEntity> facteurCaracterisationEntities = facteurCaracterisationRepository.findByNiveauAndCategorieAndLocalisationAndCritere(Constants.MIXELEC_NIVEAU, Constants.MIXELEC_CATEGORIE, id.getPays(), id.getCritere()); - if (facteurCaracterisationEntities.isPresent()) { - return mixElectriqueMapper.toMixElectrique(facteurCaracterisationMapper.toDomain(facteurCaracterisationEntities.get())); + List<FacteurCaracterisationEntity> facteurCaracterisationEntities = facteurCaracterisationRepository.findByNiveauAndCategorieAndLocalisationAndCritere(Constants.MIXELEC_NIVEAU, Constants.MIXELEC_CATEGORIE, id.getPays(), id.getCritere()); + if (!facteurCaracterisationEntities.isEmpty()) { + if (facteurCaracterisationEntities.size() > 1) { + log.warn("Il y a plusieurs mix électriques pour la même localisation {} et critère {}", id.getPays(), id.getCritere()); + } + return mixElectriqueMapper.toMixElectrique(facteurCaracterisationMapper.toDomain(facteurCaracterisationEntities.get(0))); } else { throw new ReferentielException("Mix Electrique non trouvé pour l'id " + id); } @@ -70,5 +72,4 @@ public class MixElectriqueJpaAdapter implements ReferentielPersistencePort<MixEl public List<MixElectrique> getAll() { return mixElectriqueMapper.toMixElectriques(facteurCaracterisationMapper.toDomains(facteurCaracterisationRepository.findByNiveauAndCategorie(Constants.MIXELEC_NIVEAU, Constants.MIXELEC_CATEGORIE))); } - } diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/TypeEquipementJpaAdapter.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/TypeEquipementJpaAdapter.java index e0c2e7d9d1136f0bf5f91361a5426c81fcfa7f8b..34e623df3b4c0f15516616efe18cdcb7b429ef0b 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/TypeEquipementJpaAdapter.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/TypeEquipementJpaAdapter.java @@ -2,59 +2,67 @@ package org.mte.numecoeval.referentiel.infrastructure.jpa.adapter; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.ListUtils; import org.mte.numecoeval.referentiel.domain.exception.ReferentielException; import org.mte.numecoeval.referentiel.domain.model.TypeEquipement; +import org.mte.numecoeval.referentiel.domain.model.TypeItem; import org.mte.numecoeval.referentiel.domain.ports.output.ReferentielPersistencePort; -import org.mte.numecoeval.referentiel.infrastructure.jpa.repository.TypeEquipementRepository; +import org.mte.numecoeval.referentiel.infrastructure.jpa.entity.TypeItemEntity; +import org.mte.numecoeval.referentiel.infrastructure.jpa.repository.TypeItemRepository; import org.mte.numecoeval.referentiel.infrastructure.mapper.TypeEquipementMapper; +import org.mte.numecoeval.referentiel.infrastructure.mapper.TypeItemMapper; import org.springframework.stereotype.Service; import java.util.Collection; import java.util.List; +import java.util.Optional; + +import static org.mte.numecoeval.referentiel.utils.Constants.CATEGORIE_EQUIPEMENT_PHYSIQUE; @Service @Slf4j @AllArgsConstructor -public class TypeEquipementJpaAdapter implements ReferentielPersistencePort<TypeEquipement,String> { +public class TypeEquipementJpaAdapter implements ReferentielPersistencePort<TypeEquipement, String> { + TypeItemRepository typeItemRepository; + TypeItemMapper typeItemMapper; TypeEquipementMapper typeEquipementMapper; - TypeEquipementRepository typeEquipementRepository; @Override public TypeEquipement save(TypeEquipement referentiel) throws ReferentielException { - typeEquipementRepository.save(typeEquipementMapper.toEntity(referentiel)); + var entityToSave = typeItemMapper.toEntity(typeEquipementMapper.toTypeItem(referentiel)); + if (entityToSave != null) { + typeItemRepository.save(entityToSave); + return referentiel; + } return null; } @Override public void saveAll(Collection<TypeEquipement> referentiels) throws ReferentielException { - typeEquipementRepository.saveAll(ListUtils.emptyIfNull(referentiels - .stream() - .map(typeEquipement -> typeEquipementMapper.toEntity(typeEquipement)) - .toList())); + List<TypeItem> typeItemList = typeEquipementMapper.toTypesItem(referentiels.stream().toList()); + typeItemRepository.saveAll(typeItemMapper.toEntities(typeItemList)); } @Override public TypeEquipement get(String id) throws ReferentielException { - var entityOpt= typeEquipementRepository.findById(id); - if(entityOpt.isPresent()){ - return typeEquipementMapper.toDomaine(entityOpt.get()); + if (id == null) throw new ReferentielException("Type Equipement non trouvé pour l'id null"); + + Optional<TypeItemEntity> typeItemEntities = typeItemRepository.findById(id); + if (typeItemEntities.isPresent()) { + return typeEquipementMapper.toTypeEquipement(typeItemMapper.toDomain(typeItemEntities.get())); + } else { + throw new ReferentielException("Type Equipement non trouvé pour l'id " + id); } - return null; } @Override public void purge() { - typeEquipementRepository.deleteAll(); + typeItemRepository.deleteAll(); } @Override public List<TypeEquipement> getAll() { - - return ListUtils.emptyIfNull(typeEquipementRepository.findAll()) - .stream() - .map(typeEquipementEntity -> typeEquipementMapper.toDomaine(typeEquipementEntity)) - .toList(); + List<TypeItemEntity> typeItems = typeItemRepository.findByCategorie(CATEGORIE_EQUIPEMENT_PHYSIQUE); + return typeEquipementMapper.toTypeEquipements(typeItemMapper.toDomains(typeItems)); } } diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/TypeItemJpaAdapter.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/TypeItemJpaAdapter.java new file mode 100644 index 0000000000000000000000000000000000000000..a2216c7b134a6b5cd77e8b8d533cdacb26713dfb --- /dev/null +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/adapter/TypeItemJpaAdapter.java @@ -0,0 +1,57 @@ +package org.mte.numecoeval.referentiel.infrastructure.jpa.adapter; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.mte.numecoeval.referentiel.domain.exception.ReferentielException; +import org.mte.numecoeval.referentiel.domain.model.TypeItem; +import org.mte.numecoeval.referentiel.domain.ports.output.ReferentielPersistencePort; +import org.mte.numecoeval.referentiel.infrastructure.jpa.repository.TypeItemRepository; +import org.mte.numecoeval.referentiel.infrastructure.mapper.TypeItemMapper; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.List; + +@Service +@Slf4j +@AllArgsConstructor +public class TypeItemJpaAdapter implements ReferentielPersistencePort<TypeItem, String> { + + TypeItemMapper typeItemMapper; + TypeItemRepository typeItemRepository; + + @Override + public TypeItem save(TypeItem typeItem) throws ReferentielException { + typeItemRepository.save(typeItemMapper.toEntity(typeItem)); + return typeItem; + } + + @Override + public void saveAll(Collection<TypeItem> referentiels) throws ReferentielException { + if (referentiels == null) return; + + typeItemRepository.saveAll(referentiels.stream() + .map(TypeItem -> typeItemMapper.toEntity(TypeItem)) + .toList()); + } + + @Override + public TypeItem get(String id) throws ReferentielException { + return typeItemRepository.findById(id) + .map(typeItemEntity -> typeItemMapper.toDomain(typeItemEntity)) + .orElse(null); + } + + @Override + public void purge() { + typeItemRepository.deleteAll(); + } + + @Override + public List<TypeItem> getAll() { + return typeItemRepository.findAll() + .stream() + .map(TypeItemEntity -> typeItemMapper.toDomain(TypeItemEntity)) + .toList(); + } +} \ No newline at end of file diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/entity/FacteurCaracterisationEntity.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/entity/FacteurCaracterisationEntity.java index 1f805bc5ab9a072b5fea46cfd617a69a7502190e..c679fa410b93ad92da1fa062e9f91d39982ecbfe 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/entity/FacteurCaracterisationEntity.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/entity/FacteurCaracterisationEntity.java @@ -21,14 +21,12 @@ public class FacteurCaracterisationEntity implements AbstractReferentielEntity { @Id String nom; @Id - @Column(name = "ETAPEACV") + @Column(name = "etapeacv") String etape; @Id - @Column(name = "NOMCRITERE") + @Column(name = "nomcritere") String critere; - String localisation; - String description; String niveau; String tiers; diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/entity/HypotheseEntity.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/entity/HypotheseEntity.java index ab8fc01d6afe8d1ac715682ffe993053c9d076ac..265d148edfe67fb9b6c112bd15bd3572885191d0 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/entity/HypotheseEntity.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/entity/HypotheseEntity.java @@ -27,6 +27,7 @@ public class HypotheseEntity implements AbstractReferentielEntity { String code; String valeur; String source; + String description; @Override public boolean equals(Object o) { @@ -36,11 +37,11 @@ public class HypotheseEntity implements AbstractReferentielEntity { HypotheseEntity that = (HypotheseEntity) o; - return new EqualsBuilder().append(code, that.code).append(valeur, that.valeur).append(source, that.source).isEquals(); + return new EqualsBuilder().append(code, that.code).append(valeur, that.valeur).append(source, that.source).append(description, that.description).isEquals(); } @Override public int hashCode() { - return new HashCodeBuilder(17, 37).append(code).append(valeur).append(source).toHashCode(); + return new HashCodeBuilder(17, 37).append(code).append(valeur).append(source).append(description).toHashCode(); } } diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/entity/TypeItemEntity.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/entity/TypeItemEntity.java new file mode 100644 index 0000000000000000000000000000000000000000..81ab071772f31a659c2f5e809678807bd04354df --- /dev/null +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/entity/TypeItemEntity.java @@ -0,0 +1,45 @@ +package org.mte.numecoeval.referentiel.infrastructure.jpa.entity; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import lombok.*; +import lombok.experimental.Accessors; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +@Builder +@Getter +@Setter +@Accessors(chain = true) +@NoArgsConstructor +@AllArgsConstructor +@Entity(name = "REF_TYPE_ITEM") +public class TypeItemEntity implements AbstractReferentielEntity { + @Id + String type; + String categorie; + boolean serveur; + String commentaire; + Double dureeVieDefaut; + // ref de l'hypothèse nécesssaire pour le calcul de l'impact de cet l'item + String refHypothese; + String source; + // Référence de l'item par défaut, permet des correspondances en cas d'absence de correspondance directe. + String refItemParDefaut; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || getClass() != o.getClass()) return false; + + TypeItemEntity that = (TypeItemEntity) o; + + return new EqualsBuilder().append(categorie, that.categorie).append(serveur, that.serveur).append(type, that.type).append(commentaire, that.commentaire).append(dureeVieDefaut, that.dureeVieDefaut).append(refHypothese, that.refHypothese).append(source, that.source).isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37).append(type).append(categorie).append(serveur).append(commentaire).append(dureeVieDefaut).append(refHypothese).append(source).toHashCode(); + } +} diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/repository/FacteurCaracterisationRepository.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/repository/FacteurCaracterisationRepository.java index bd6cb54385e58bf83a00474ea462766cb8a10ab0..da8d00f777b6391be92df8d6dbfcbd17164bf48f 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/repository/FacteurCaracterisationRepository.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/repository/FacteurCaracterisationRepository.java @@ -6,6 +6,7 @@ import org.mte.numecoeval.referentiel.infrastructure.jpa.entity.FacteurCaracteri import org.mte.numecoeval.referentiel.infrastructure.jpa.entity.id.FacteurCaracterisationIdEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.rest.core.annotation.RepositoryRestResource; import java.util.List; @@ -27,7 +28,17 @@ public interface FacteurCaracterisationRepository extends JpaRepository<FacteurC @Modifying void deleteByNiveauAndTiers(String niveau, String tiers); - Optional<FacteurCaracterisationEntity> findByNiveauAndCategorieAndLocalisationAndCritere(String niveau, String categorie, String localisation, String critere); + @Query(""" + SELECT fc FROM #{#entityName} fc WHERE + ((?1 IS NULL) OR (?1 IS NOT NULL AND fc.critere = ?1)) AND + ((?2 IS NULL) OR (?2 IS NOT NULL AND fc.etape = ?2)) AND + ((?3 IS NULL) OR (?3 IS NOT NULL AND fc.nom = ?3)) AND + ((?4 IS NULL) OR (?4 IS NOT NULL AND fc.localisation = ?4)) AND + ((?5 IS NULL) OR (?5 IS NOT NULL AND fc.categorie = ?5)) + """) + List<FacteurCaracterisationEntity> findByCritereAndEtapeAndNomAndLocalisationAndCategorie(String nomcritere, String etape, String nom, String localisation, String categorie); + + List<FacteurCaracterisationEntity> findByNiveauAndCategorieAndLocalisationAndCritere(String niveau, String categorie, String localisation, String critere); Optional<FacteurCaracterisationEntity> findByNomAndEtapeAndCritere(String nom, String etape, String critere); diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/repository/TypeItemRepository.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/repository/TypeItemRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..f824bf685b2d8c6de84c01eed4f945e5f9bd3623 --- /dev/null +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/jpa/repository/TypeItemRepository.java @@ -0,0 +1,16 @@ +package org.mte.numecoeval.referentiel.infrastructure.jpa.repository; + +import io.swagger.v3.oas.annotations.tags.Tag; +import org.mte.numecoeval.referentiel.infrastructure.jpa.entity.TypeItemEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.rest.core.annotation.RepositoryRestResource; + +import java.util.List; + +@RepositoryRestResource(path = "TypeItem", itemResourceRel = "TypesEquipements") +@Tag(name = "TypeItem - CRUD/Spring Data REST") +public interface TypeItemRepository extends JpaRepository<TypeItemEntity, String> { + + List<TypeItemEntity> findByCategorie(String categorie); + +} diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/mapper/FacteurCaracterisationMapper.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/mapper/FacteurCaracterisationMapper.java index 57baea0f12f5bd1e88a50d633f8bebca0afe2339..42df19c67a11f8140d857b6d83f57559277a2a3c 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/mapper/FacteurCaracterisationMapper.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/mapper/FacteurCaracterisationMapper.java @@ -30,4 +30,7 @@ public interface FacteurCaracterisationMapper { List<FacteurCaracterisation> toDomainsFromDTO(List<FacteurCaracterisationDTO> iesDTO); FacteurCaracterisationDTO toDTO(FacteurCaracterisation facteurCaracterisation); + + List<FacteurCaracterisationDTO> toDTOs(List<FacteurCaracterisation> facteurCaracterisations); + } diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/mapper/TypeEquipementMapper.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/mapper/TypeEquipementMapper.java index aef63367511cdd0991bc65ce28de9f84b2100c66..5af2f6ad6fd476fb60523d75e0020af5b34cc730 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/mapper/TypeEquipementMapper.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/mapper/TypeEquipementMapper.java @@ -1,9 +1,11 @@ package org.mte.numecoeval.referentiel.infrastructure.mapper; import org.mapstruct.Mapper; -import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.TypeEquipementDTO; +import org.mapstruct.Mapping; import org.mte.numecoeval.referentiel.domain.model.TypeEquipement; +import org.mte.numecoeval.referentiel.domain.model.TypeItem; import org.mte.numecoeval.referentiel.infrastructure.jpa.entity.TypeEquipementEntity; +import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.TypeEquipementDTO; import java.util.Collection; import java.util.List; @@ -12,12 +14,27 @@ import java.util.List; public interface TypeEquipementMapper { TypeEquipement toDomaine(TypeEquipementEntity typeEquipementEntity); + + List<TypeEquipement> toDomaines(List<TypeEquipementEntity> typeEquipementEntities); + TypeEquipement toDomaine(TypeEquipementDTO typeEquipementDTO); TypeEquipementEntity toEntity(TypeEquipement typeEquipement); + List<TypeEquipementEntity> toEntities(Collection<TypeEquipement> typeEquipements); TypeEquipementDTO toDto(TypeEquipement typeEquipement); + @Mapping(target = "refItemParDefaut", source = "refEquipementParDefaut") + @Mapping(target = "categorie", expression = "java(org.mte.numecoeval.referentiel.utils.Constants.CATEGORIE_EQUIPEMENT_PHYSIQUE)") + TypeItem toTypeItem(TypeEquipement typeEquipement); + + List<TypeItem> toTypesItem(List<TypeEquipement> typesEquipement); + + @Mapping(target = "refEquipementParDefaut", source = "refItemParDefaut") + TypeEquipement toTypeEquipement(TypeItem typeItem); + + List<TypeEquipement> toTypeEquipements(List<TypeItem> typeItems); + } diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/mapper/TypeItemMapper.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/mapper/TypeItemMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..16e9ec80b96b31bf8ad23d3ad69d0d78322bc19b --- /dev/null +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/mapper/TypeItemMapper.java @@ -0,0 +1,27 @@ +package org.mte.numecoeval.referentiel.infrastructure.mapper; + +import org.mapstruct.Mapper; +import org.mte.numecoeval.referentiel.domain.model.TypeItem; +import org.mte.numecoeval.referentiel.infrastructure.jpa.entity.TypeItemEntity; +import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.TypeItemDTO; + +import java.util.Collection; +import java.util.List; + +@Mapper(componentModel = "spring") +public interface TypeItemMapper { + + TypeItem toDomain(TypeItemEntity TypeItemEntity); + + List<TypeItem> toDomains(List<TypeItemEntity> TypeItemEntities); + + TypeItem toDomain(TypeItemDTO TypeItemDTO); + + TypeItemEntity toEntity(TypeItem TypeItem); + + List<TypeItemEntity> toEntities(Collection<TypeItem> TypeItems); + + TypeItemDTO toDTO(TypeItem TypeItem); + + +} diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/facteurcaracterisation/ReferentielFacteurCaracterisationRestApi.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/facteurcaracterisation/ReferentielFacteurCaracterisationRestApi.java index 056cd35dcb397e3d4a76b3d8b267ca8219c773e3..b172e0c1e562640bb270631991b38d3369fa767c 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/facteurcaracterisation/ReferentielFacteurCaracterisationRestApi.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/facteurcaracterisation/ReferentielFacteurCaracterisationRestApi.java @@ -1,6 +1,7 @@ package org.mte.numecoeval.referentiel.infrastructure.restapi.controller.facteurcaracterisation; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -11,36 +12,44 @@ import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; +import java.util.List; + public interface ReferentielFacteurCaracterisationRestApi { - @Operation(summary = "Endpoint interne à NumEcoEval - Récupération d'un Facteur de Caractérisation", + @Operation(summary = "Endpoint interne à NumEcoEval - Récupération des Facteurs de Caractérisation", description = """ Endpoint interne utilisé dans la génération des indicateurs par le module api-calcul de NumEcoEval. - Récupération d'un impact équipement en fonction de 3 paramètres: + Récupération des Facteurs de Caractérisation en fonction de 5 paramètres: <ul> - <li>Le nom du facteur de caractérisation: nom</li> - <li>L'étape ACV: etape</li> - <li>Le critère d'impact: critere</li> + <li>Le nom du critère d'impact écologique: critere</li> + <li>Le code de l'étape ACV: etapeacv</li> + <li>Le nom du facteur de caractérisation recherché: nom</li> + <li>La localisation: localisation</li> + <li>La catégorie: categorie</li> </ul> . """, tags = "Interne NumEcoEval", operationId = "getFacteurCaracterisation") @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "Facteur Caractérisation trouvé", - content = {@Content(mediaType = "application/json", schema = @Schema(implementation = FacteurCaracterisationDTO.class))}), + @ApiResponse(responseCode = "200", description = "Liste des Facteurs de Caractérisation trouvés", + content = {@Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = FacteurCaracterisationDTO.class)))}), @ApiResponse(responseCode = "400", description = "Invalid request", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponseDTO.class))}), @ApiResponse(responseCode = "404", description = "Facteur Caractérisation non trouvé", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponseDTO.class))})}) @GetMapping(path = "/referentiel/facteursCaracterisation", produces = MediaType.APPLICATION_JSON_VALUE) - FacteurCaracterisationDTO get( - @RequestParam - @Schema(description = "Nom du facteur de caractérisation recherché") final String nom, - @RequestParam + List<FacteurCaracterisationDTO> get( + @RequestParam(required = false) @Schema(description = "Nom du critère d'impact écologique") final String critere, - @RequestParam - @Schema(description = "Code de l'étape ACV") final String etapeacv + @RequestParam(required = false) + @Schema(description = "Code de l'étape ACV") final String etapeacv, + @RequestParam(required = false) + @Schema(description = "Nom du facteur de caractérisation recherché") final String nom, + @RequestParam(required = false) + @Schema(description = "Nom de la localisation") final String localisation, + @RequestParam(required = false) + @Schema(description = "Nom de la catégorie") final String categorie ); } diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/facteurcaracterisation/ReferentielFacteurCaracterisationRestApiImpl.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/facteurcaracterisation/ReferentielFacteurCaracterisationRestApiImpl.java index c71b396f0fc4c3075f29dca64b267e439e84e223..6ae975f47cf38c6c25868b1027a94eac3fdfe38a 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/facteurcaracterisation/ReferentielFacteurCaracterisationRestApiImpl.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/facteurcaracterisation/ReferentielFacteurCaracterisationRestApiImpl.java @@ -4,7 +4,6 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.AllArgsConstructor; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.mte.numecoeval.referentiel.domain.exception.ReferentielException; import org.mte.numecoeval.referentiel.domain.ports.input.impl.ImportFacteurCaracterisationPortImpl; import org.mte.numecoeval.referentiel.infrastructure.adapter.export.FacteurCaracterisationCsvExportService; @@ -12,7 +11,6 @@ import org.mte.numecoeval.referentiel.infrastructure.jpa.entity.FacteurCaracteri import org.mte.numecoeval.referentiel.infrastructure.restapi.controller.BaseExportReferentiel; import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.FacteurCaracterisationDTO; import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.RapportImportDTO; -import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.id.FacteurCaracterisationIdDTO; import org.mte.numecoeval.referentiel.infrastructure.restapi.facade.FacteurCaracterisationFacade; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.RestController; @@ -20,6 +18,7 @@ import org.springframework.web.multipart.MultipartFile; import org.springframework.web.server.ResponseStatusException; import java.io.IOException; +import java.util.List; @RestController @Slf4j @@ -31,17 +30,12 @@ public class ReferentielFacteurCaracterisationRestApiImpl implements BaseExportR @SneakyThrows @Override - public FacteurCaracterisationDTO get(String nom, String critere, String etapeacv) { - - FacteurCaracterisationIdDTO id = FacteurCaracterisationIdDTO.builder() - .nom(StringUtils.trim(nom)) - .critere(critere) - .etape(etapeacv) - .build(); - - return referentielFacade.get(id); + public List<FacteurCaracterisationDTO> get(String critere, String etapeacv, String nom, String localisation, String categorie) { + String[] params = {critere, etapeacv, nom, localisation, categorie}; + return referentielFacade.getByFilters(params); } + @Override public RapportImportDTO importCSV(MultipartFile fichier, String mode) throws IOException, ReferentielException { if (fichier == null || fichier.isEmpty()) { @@ -66,6 +60,6 @@ public class ReferentielFacteurCaracterisationRestApiImpl implements BaseExportR @Override public void exportCSV(HttpServletResponse servletResponse) throws IOException { - exportCSV(servletResponse, csvExportService, "facteurCaracterisation"); + exportCSV(servletResponse, csvExportService, "facteursCaracterisation"); } } diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/typeequipement/ReferentielTypeEquipementRestApiImpl.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/typeequipement/ReferentielTypeEquipementRestApiImpl.java index 13b16bec0eb738adf4b449529f099b8222ad21e1..2b49476f71aeb9efdf3e9a23e7f6326be658e251 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/typeequipement/ReferentielTypeEquipementRestApiImpl.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/typeequipement/ReferentielTypeEquipementRestApiImpl.java @@ -3,13 +3,13 @@ package org.mte.numecoeval.referentiel.infrastructure.restapi.controller.typeequ import jakarta.servlet.http.HttpServletResponse; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.TypeEquipementDTO; import org.mte.numecoeval.referentiel.domain.exception.ReferentielException; +import org.mte.numecoeval.referentiel.domain.model.TypeEquipement; import org.mte.numecoeval.referentiel.domain.ports.input.impl.ImportTypeEquipementPortImpl; import org.mte.numecoeval.referentiel.infrastructure.adapter.export.TypeEquipementCsvExportService; -import org.mte.numecoeval.referentiel.infrastructure.jpa.entity.TypeEquipementEntity; import org.mte.numecoeval.referentiel.infrastructure.restapi.controller.BaseExportReferentiel; import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.RapportImportDTO; +import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.TypeEquipementDTO; import org.mte.numecoeval.referentiel.infrastructure.restapi.facade.TypeEquipementFacade; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.RestController; @@ -22,11 +22,11 @@ import java.util.List; @RestController @Slf4j @AllArgsConstructor -public class ReferentielTypeEquipementRestApiImpl implements BaseExportReferentiel<TypeEquipementEntity>, ReferentielTypeEquipementRestApi, ReferentielAdministrationTypeEquipementRestApi { +public class ReferentielTypeEquipementRestApiImpl implements BaseExportReferentiel<TypeEquipement>, ReferentielTypeEquipementRestApi, ReferentielAdministrationTypeEquipementRestApi { - private TypeEquipementFacade typeEquipementFacade; + private TypeEquipementFacade typeEquipementFacade; - private TypeEquipementCsvExportService csvExportService; + private TypeEquipementCsvExportService csvExportService; @Override public RapportImportDTO importCSV(MultipartFile fichier) throws IOException, ReferentielException { diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/typeitem/ReferentielAdministrationTypeItemRestApi.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/typeitem/ReferentielAdministrationTypeItemRestApi.java new file mode 100644 index 0000000000000000000000000000000000000000..3c00bb6e5c7938e0d5389e03913fa49e5489e35a --- /dev/null +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/typeitem/ReferentielAdministrationTypeItemRestApi.java @@ -0,0 +1,57 @@ +package org.mte.numecoeval.referentiel.infrastructure.restapi.controller.typeitem; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import jakarta.servlet.http.HttpServletResponse; +import org.mte.numecoeval.referentiel.domain.exception.ReferentielException; +import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.ErrorResponseDTO; +import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.RapportImportDTO; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; + +public interface ReferentielAdministrationTypeItemRestApi { + + @Operation( + summary = "Alimentation du référentiel Type Item par csv : annule et remplace.", + description = """ + Le référentiel est global à tout le système. L’import se fait uniquement avec un fichier CSV. + Lors de l’import, les données précédentes sont supprimées. + <ul> + <li>Entrée : Le fichier CSV du référentiel</li> + <li>Sortie : Rapport du fichier CSV (nombre de lignes totales, nombre de lignes en erreur, nombre de lignes traitées, liste des erreurs par lignes).</li> + </ul> + """, + tags = {"Import Référentiels"}, + operationId = "importTypeItemCSV" + ) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Rapport d'import du fichier CSV"), + @ApiResponse(responseCode = "400", description = "Invalid request", + content = {@Content(mediaType = "application/json", + schema = @Schema(implementation = ErrorResponseDTO.class))})}) + @PostMapping(path = "/referentiel/typeItem/csv", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + RapportImportDTO importCSV(@RequestPart("file") MultipartFile file) throws IOException, ReferentielException; + + + @Operation( + summary = "Exporter les impacts des types d'items sous format csv", + description = """ + <ul> + <li>Entrée : Aucune </li> + <li>Sortie : Renvoie la liste des étapes de ref_TypeItem </li> + </ul> + """, + tags = {"Export Référentiels"}, + operationId = "exportTypeItemCSV" + ) + @GetMapping("/referentiel/typeItem/csv") + void exportCSV(HttpServletResponse servletResponse) throws IOException; +} diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/typeitem/ReferentielTypeItemRestApi.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/typeitem/ReferentielTypeItemRestApi.java new file mode 100644 index 0000000000000000000000000000000000000000..bbdab44b4a800753bf5d79e44f6bba42dc37d4b9 --- /dev/null +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/typeitem/ReferentielTypeItemRestApi.java @@ -0,0 +1,63 @@ +package org.mte.numecoeval.referentiel.infrastructure.restapi.controller.typeitem; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.mte.numecoeval.referentiel.domain.exception.ReferentielException; +import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.ErrorResponseDTO; +import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.TypeItemDTO; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +import java.util.List; + +public interface ReferentielTypeItemRestApi { + + @Operation( + summary = "Endpoint interne à NumEcoEval - Récupération de tous les types d'items", + description = """ + Endpoint interne utilisé à la réception de données d'entrées par le module api-expositiondonneesentrees de NumEcoEval. + Renvoie l'intégralité des types d'items utilisables par NumEcoEval. + + Les types d'items servent notamment à alimenter la durée de vie par défaut des items + reçues. + """, + tags = "Interne NumEcoEval", + operationId = "getAllTypeItem" + ) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Types Item", + content = {@Content(mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = TypeItemDTO.class)))}), + @ApiResponse(responseCode = "400", description = "Invalid request", + content = {@Content(mediaType = "application/json", + schema = @Schema(implementation = ErrorResponseDTO.class))}), + @ApiResponse(responseCode = "404", description = "Types Item non trouvé", content = {@Content(mediaType = "application/json", + schema = @Schema(implementation = ErrorResponseDTO.class))})}) + @GetMapping(path = "/referentiel/typesItem", produces = MediaType.APPLICATION_JSON_VALUE) + List<TypeItemDTO> getTypesItem(); + + @Operation( + summary = "Endpoint interne à NumEcoEval - Récupération d'items via leur type", + description = """ + Endpoint interne utilisé à la réception de données d'entrées par le module api-expositiondonneesentrees de NumEcoEval. Renvoie l'intégralité des types d'items d'un certain type. + """, + tags = "Interne NumEcoEval", + operationId = "getTypeItem" + ) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Types Item", + content = {@Content(mediaType = "application/json", + schema = @Schema(implementation = TypeItemDTO.class))}), + @ApiResponse(responseCode = "400", description = "Invalid request", + content = {@Content(mediaType = "application/json", + schema = @Schema(implementation = ErrorResponseDTO.class))}), + @ApiResponse(responseCode = "404", description = "Types Item non trouvé", content = {@Content(mediaType = "application/json", + schema = @Schema(implementation = ErrorResponseDTO.class))})}) + @GetMapping(path = "/referentiel/typesItem/{type}", produces = MediaType.APPLICATION_JSON_VALUE) + TypeItemDTO getTypeItem(@PathVariable @Schema(description = "type recherché") String type) throws ReferentielException; +} diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/typeitem/ReferentielTypeItemRestApiImpl.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/typeitem/ReferentielTypeItemRestApiImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..50fb8d329aa5667969c8ef8a451ce8ecbad58a4c --- /dev/null +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/typeitem/ReferentielTypeItemRestApiImpl.java @@ -0,0 +1,59 @@ +package org.mte.numecoeval.referentiel.infrastructure.restapi.controller.typeitem; + +import jakarta.servlet.http.HttpServletResponse; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.mte.numecoeval.referentiel.domain.exception.ReferentielException; +import org.mte.numecoeval.referentiel.domain.ports.input.impl.ImportTypeItemPortImpl; +import org.mte.numecoeval.referentiel.infrastructure.adapter.export.TypeItemCsvExportService; +import org.mte.numecoeval.referentiel.infrastructure.jpa.entity.TypeItemEntity; +import org.mte.numecoeval.referentiel.infrastructure.restapi.controller.BaseExportReferentiel; +import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.RapportImportDTO; +import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.TypeItemDTO; +import org.mte.numecoeval.referentiel.infrastructure.restapi.facade.TypeItemFacade; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.server.ResponseStatusException; + +import java.io.IOException; +import java.util.List; + +@RestController +@Slf4j +@AllArgsConstructor +public class ReferentielTypeItemRestApiImpl implements BaseExportReferentiel<TypeItemEntity>, ReferentielTypeItemRestApi, ReferentielAdministrationTypeItemRestApi { + + private TypeItemFacade TypeItemFacade; + + private TypeItemCsvExportService csvExportService; + + @Override + public RapportImportDTO importCSV(MultipartFile fichier) throws IOException, ReferentielException { + if (fichier == null || fichier.isEmpty()) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Le fichier n'existe pas ou alors il est vide"); + } + var rapportImport = new ImportTypeItemPortImpl().importCSV(fichier.getInputStream()); + TypeItemFacade.purgeAndAddAll(rapportImport.getObjects()); + return new RapportImportDTO( + fichier.getOriginalFilename(), + rapportImport.getErreurs(), + rapportImport.getNbrLignesImportees() + ); + } + + @Override + public TypeItemDTO getTypeItem(String type) throws ReferentielException { + return TypeItemFacade.getTypeItemForType(type); + } + + @Override + public List<TypeItemDTO> getTypesItem() { + return TypeItemFacade.getAllTypesItem(); + } + + @Override + public void exportCSV(HttpServletResponse servletResponse) throws IOException { + exportCSV(servletResponse, csvExportService, "typeItem"); + } +} diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/dto/HypotheseDTO.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/dto/HypotheseDTO.java index cfb8931abfbb6657c620b5409683029929e8b8e2..4fae57c7ad424360bd98e68a1016680d7652168e 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/dto/HypotheseDTO.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/dto/HypotheseDTO.java @@ -30,4 +30,8 @@ public class HypotheseDTO implements Serializable { description = "Source de l'hypothèse" ) String source; + @Schema( + description = "Description de l'hypothèse" + ) + String description; } diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/dto/TypeItemDTO.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/dto/TypeItemDTO.java new file mode 100644 index 0000000000000000000000000000000000000000..ddf50fe98d054369832457107c121025443033f4 --- /dev/null +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/dto/TypeItemDTO.java @@ -0,0 +1,54 @@ +package org.mte.numecoeval.referentiel.infrastructure.restapi.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import lombok.experimental.Accessors; +import lombok.experimental.FieldDefaults; + +import java.io.Serializable; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = true) +@FieldDefaults(level = AccessLevel.PRIVATE) +@EqualsAndHashCode +@Builder +@Schema( + description = "Référentiel des types d'items utilisables dans le système. La clé du référentiel est le champ type." +) +public class TypeItemDTO implements Serializable { + @Schema( + description = "Type d'item, clé du référentiel" + ) + String type; + @Schema( + description = "Catégorie de l'item" + ) + String categorie; + @Schema( + description = "Flag indiquant si l'item est un serveur" + ) + boolean serveur; + @Schema( + description = "Commentaire de l'entrée dans le référentiel" + ) + String commentaire; + @Schema( + description = "Durée de vie par défaut de ce type d'item" + ) + Double dureeVieDefaut; + @Schema( + description = "Référence vers l'hypothèse nécessaire pour le calcul d'impact de cet item" + ) + String refHypothese; + @Schema( + description = "Source de l'information du référentiel" + ) + String source; + @Schema( + description = "Référence de l'item par défaut, permet des correspondances en cas d'absence de correspondance directe" + ) + String refItemParDefaut; +} diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/facade/FacteurCaracterisationFacade.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/facade/FacteurCaracterisationFacade.java index f959e8c849da1dd0712d46da8cb0f8ce5effe2ba..f603f84ea3aa4c8bfe8c57fb8c9a98d194535fcf 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/facade/FacteurCaracterisationFacade.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/facade/FacteurCaracterisationFacade.java @@ -30,6 +30,11 @@ public class FacteurCaracterisationFacade { return mapper.toDTO(facteurCaracterisation); } + public List<FacteurCaracterisationDTO> getByFilters(String... params) throws ReferentielException { + List<FacteurCaracterisation> facteurCaracterisation = persistencePort.findByFilters(params[0], params[1], params[2], params[3], params[4]); + return mapper.toDTOs(facteurCaracterisation); + } + public void purgeAndAddAll(List<FacteurCaracterisationDTO> fcsDTO) throws ReferentielException { persistencePort.purge(); persistencePort.saveAll(mapper.toDomainsFromDTO(fcsDTO)); diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/facade/TypeItemFacade.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/facade/TypeItemFacade.java new file mode 100644 index 0000000000000000000000000000000000000000..b15e0ec8cd7c00c19783e87ce2d0258c05b3c2c0 --- /dev/null +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/infrastructure/restapi/facade/TypeItemFacade.java @@ -0,0 +1,44 @@ +package org.mte.numecoeval.referentiel.infrastructure.restapi.facade; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.mte.numecoeval.referentiel.domain.exception.ReferentielException; +import org.mte.numecoeval.referentiel.domain.model.TypeItem; +import org.mte.numecoeval.referentiel.domain.ports.output.ReferentielPersistencePort; +import org.mte.numecoeval.referentiel.infrastructure.mapper.TypeItemMapper; +import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.TypeItemDTO; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@Slf4j +@AllArgsConstructor +public class TypeItemFacade { + + private ReferentielPersistencePort<TypeItem, String> persistencePort; + private TypeItemMapper mapper; + + public TypeItemDTO getTypeItemForType(String type) throws ReferentielException { + var TypeItem = persistencePort.get(type); + if (TypeItem != null) { + return mapper.toDTO(TypeItem); + } + return null; + } + + public List<TypeItemDTO> getAllTypesItem() { + return persistencePort.getAll().stream() + .map(TypeItem -> mapper.toDTO(TypeItem)) + .toList(); + } + + public void purgeAndAddAll(List<TypeItemDTO> types) throws ReferentielException { + if (types == null) return; + persistencePort.purge(); + persistencePort.saveAll(types.stream() + .map(TypeItemDTO -> mapper.toDomain(TypeItemDTO)) + .toList()); + } + +} diff --git a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/utils/Constants.java b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/utils/Constants.java index 27b7430f4e7a134e442d0c8d784d914db06572d7..15bc08bf29b9d2e364ede56ce5806202c93acac4 100644 --- a/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/utils/Constants.java +++ b/services/api-referentiel/src/main/java/org/mte/numecoeval/referentiel/utils/Constants.java @@ -9,5 +9,6 @@ public class Constants { public static final String MIXELEC_NOM_LOW_VOLTAGE = "Electricity Mix/ Production mix/ Low voltage/ "; public static final String RESEAU_NIVEAU = "3-System"; public static final String RESEAU_TIERS = "Network"; + public static final String CATEGORIE_EQUIPEMENT_PHYSIQUE = "EquipementPhysique"; } diff --git a/services/api-referentiel/src/main/resources/schema.sql b/services/api-referentiel/src/main/resources/schema.sql index e52a333a27706cac1ca02a000762765e8a1b25f2..1f910575e8599bc34ff0e3036a01cff8b0b4c2f7 100644 --- a/services/api-referentiel/src/main/resources/schema.sql +++ b/services/api-referentiel/src/main/resources/schema.sql @@ -18,6 +18,7 @@ CREATE TABLE IF NOT EXISTS ref_hypothese code varchar(255) NOT NULL, "source" varchar(255) NULL, valeur varchar(255) NULL, + description varchar(255) NULL, CONSTRAINT ref_hypothese_pkey PRIMARY KEY (code) ); @@ -32,6 +33,19 @@ CREATE TABLE IF NOT EXISTS ref_type_equipement CONSTRAINT ref_type_equipement_pkey PRIMARY KEY (type) ); +CREATE TABLE IF NOT EXISTS ref_type_item +( + "type" varchar(255) NOT NULL, + categorie varchar(255) NULL, + commentaire varchar(255) NULL, + duree_vie_defaut float8 NULL, + ref_conso_moyenne varchar(255) NULL, + serveur bool NOT NULL, + "source" varchar(255) NULL, + ref_item_par_defaut varchar(255) NULL, + CONSTRAINT ref_type_item_pkey PRIMARY KEY (type) +); + CREATE TABLE IF NOT EXISTS ref_impact_messagerie ( constante_coefficient_directeur float8 NULL, diff --git a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/domain/port/input/ImportTypeItemPortTest.java b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/domain/port/input/ImportTypeItemPortTest.java new file mode 100644 index 0000000000000000000000000000000000000000..cf5bb6a02d7702e9fbbd37ac1bb9bf905c91d7ac --- /dev/null +++ b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/domain/port/input/ImportTypeItemPortTest.java @@ -0,0 +1,115 @@ +package org.mte.numecoeval.referentiel.domain.port.input; + +import org.junit.jupiter.api.Test; +import org.mte.numecoeval.referentiel.domain.ports.input.ImportCSVReferentielPort; +import org.mte.numecoeval.referentiel.domain.ports.input.impl.ImportTypeItemPortImpl; +import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.TypeItemDTO; +import org.springframework.util.ResourceUtils; + +import java.io.*; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.*; + +class ImportTypeItemPortTest { + + ImportCSVReferentielPort<TypeItemDTO> importPortToTest = new ImportTypeItemPortImpl(); + + @Test + void importCSV_shouldImportAllDatas() throws Exception { + File file = ResourceUtils.getFile("classpath:csv/unit/typeItem.csv"); + var resultatImport = importPortToTest.importCSV(new FileInputStream(file)); + + assertEquals(2, resultatImport.getNbrLignesImportees()); + assertEquals(0, resultatImport.getErreurs().size()); + assertEquals(2, resultatImport.getObjects().size()); + assertTrue(resultatImport.getObjects().stream().anyMatch(typeItemDTO -> + "Serveur".equals(typeItemDTO.getType()) + && typeItemDTO.getCategorie().isEmpty() + && typeItemDTO.isServeur() + && "Exemple de serveur basique".equals(typeItemDTO.getCommentaire()) + && Double.valueOf(6.0).equals(typeItemDTO.getDureeVieDefaut()) + && "NegaOctet".equals(typeItemDTO.getSource()) + && "serveur_par_defaut".equals(typeItemDTO.getRefItemParDefaut()) + ) + ); + assertTrue(resultatImport.getObjects().stream().anyMatch(typeItemDTO -> + "deplacement voiture hybride".equals(typeItemDTO.getType()) + && "deplacement_hybride".equals(typeItemDTO.getCategorie()) + && !typeItemDTO.isServeur() + && "Exemple d'opération non it".equals(typeItemDTO.getCommentaire()) + && Double.valueOf(50.0).equals(typeItemDTO.getDureeVieDefaut()) + && "SSG".equals(typeItemDTO.getSource()) + && "deplacement_voiture_hybride".equals(typeItemDTO.getRefItemParDefaut()) + ) + ); + } + + @Test + void importCSV_whenErrorInMiddleOfFile_shouldImportDatasWithErrors() throws Exception { + File file = ResourceUtils.getFile("classpath:csv/unit/typeItem_errorInMiddle.csv"); + var resultatImport = importPortToTest.importCSV(new FileInputStream(file)); + + assertEquals(2, resultatImport.getNbrLignesImportees()); + assertEquals(1, resultatImport.getErreurs().size()); + assertTrue(resultatImport.getErreurs().stream().anyMatch("La ligne n°3 est invalide : La colonne type ne peut être vide"::equals)); + assertEquals(2, resultatImport.getObjects().size()); + assertTrue(resultatImport.getObjects().stream().anyMatch(typeItemDTO -> + "Serveur".equals(typeItemDTO.getType()) + && typeItemDTO.getCategorie().isEmpty() + && typeItemDTO.isServeur() + && "Exemple de serveur basique".equals(typeItemDTO.getCommentaire()) + && Double.valueOf(6.0).equals(typeItemDTO.getDureeVieDefaut()) + && "NegaOctet".equals(typeItemDTO.getSource()) + && "serveur_par_defaut".equals(typeItemDTO.getRefItemParDefaut()) + ) + ); + assertTrue(resultatImport.getObjects().stream().anyMatch(typeItemDTO -> + "deplacement voiture hybride".equals(typeItemDTO.getType()) + && "deplacement_hybride".equals(typeItemDTO.getCategorie()) + && !typeItemDTO.isServeur() + && "Exemple d'opération non it".equals(typeItemDTO.getCommentaire()) + && Double.valueOf(50.0).equals(typeItemDTO.getDureeVieDefaut()) + && "SSG".equals(typeItemDTO.getSource()) + && "deplacement_voiture_hybride".equals(typeItemDTO.getRefItemParDefaut()) + ) + ); + } + + @Test + void importCSV_whenWrongFile_shouldReturnOnlyErrors() throws Exception { + File file = ResourceUtils.getFile("classpath:csv/unit/wrongCSVFile.csv"); + var resultatImport = importPortToTest.importCSV(new FileInputStream(file)); + + assertEquals(0, resultatImport.getNbrLignesImportees()); + assertEquals(1, resultatImport.getErreurs().size()); + assertTrue(resultatImport.getErreurs().stream().anyMatch("La ligne n°2 est invalide : Entêtes incohérentes"::equals)); + } + + @Test + void importCSV_whenStreamAlreadyClosedShouldReturnReportWithOneError() throws IOException { + DataInputStream dataInputStream = mock(DataInputStream.class); + doNothing().when(dataInputStream).close(); + + var resultatImport = importPortToTest.importCSV(dataInputStream); + + verify(dataInputStream).close(); + assertEquals(0, resultatImport.getNbrLignesImportees()); + assertEquals(1, resultatImport.getErreurs().size()); + assertEquals("Le fichier CSV n'a pas pu être lu.", resultatImport.getErreurs().get(0)); + } + + @Test + void importCSV_whenFileNotFoundShouldReturnReportWithOneError() throws IOException { + DataInputStream dataInputStream = mock(DataInputStream.class); + doThrow(new FileNotFoundException("start Read csv etape")).when(dataInputStream).close(); + + var resultatImport = importPortToTest.importCSV(dataInputStream); + + verify(dataInputStream).close(); + assertEquals(0, resultatImport.getNbrLignesImportees()); + assertEquals(1, resultatImport.getErreurs().size()); + assertEquals("Le fichier CSV n'a pas pu être lu.", resultatImport.getErreurs().get(0)); + } +} diff --git a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/factory/TestDataFactory.java b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/factory/TestDataFactory.java index 53bc5801502b2dd52f92a827d92b0d8863318d12..6082c03d5e511d913efc700801eb8dbe79f3d593 100644 --- a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/factory/TestDataFactory.java +++ b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/factory/TestDataFactory.java @@ -82,22 +82,24 @@ public class TestDataFactory { } public static class HypotheseFactory { - public static HypotheseDTO dto(String code, String valeur, String source) { - return new HypotheseDTO(code, valeur, source); + public static HypotheseDTO dto(String code, String valeur, String source, String description) { + return new HypotheseDTO(code, valeur, source, description); } - public static Hypothese domain(String code, String valeur, String source) { + public static Hypothese domain(String code, String valeur, String source, String description) { return new Hypothese() .setCode(code) .setValeur(valeur) - .setSource(source); + .setSource(source) + .setDescription(description); } - public static HypotheseEntity entity(String code, String valeur, String source) { + public static HypotheseEntity entity(String code, String valeur, String source, String description) { return new HypotheseEntity() .setCode(code) .setValeur(valeur) - .setSource(source); + .setSource(source) + .setDescription(description); } public static HypotheseIdDTO idDTO(String code) { @@ -144,6 +146,38 @@ public class TestDataFactory { } } + public static class TypeItemFactory { + public static TypeItemDTO dto(String type, String categorie, boolean estUnServeur, String commentaire, Double dureeVieDefaut, String refHypothese, String source, String refItemParDefaut) { + return TypeItemDTO.builder() + .type(type) + .categorie(categorie) + .serveur(estUnServeur) + .dureeVieDefaut(dureeVieDefaut) + .refHypothese(refHypothese) + .source(source) + .commentaire(commentaire) + .refItemParDefaut(refItemParDefaut) + .build(); + } + + public static TypeItem domain(String type, String categorie, boolean estUnServeur, String commentaire, Double dureeVieDefaut, String refHypothese, String source, String refItemParDefaut) { + return TypeItem.builder() + .type(type) + .categorie(categorie) + .serveur(estUnServeur) + .dureeVieDefaut(dureeVieDefaut) + .refHypothese(refHypothese) + .source(source) + .commentaire(commentaire) + .refItemParDefaut(refItemParDefaut) + .build(); + } + + public static TypeItemEntity entity(String type, String categorie, boolean estUnServeur, String commentaire, Double dureeVieDefaut, String refHypothese, String source, String refItemParDefaut) { + return new TypeItemEntity(type, categorie, estUnServeur, commentaire, dureeVieDefaut, refHypothese, source, refItemParDefaut); + } + } + public static class MixElectriqueFactory { diff --git a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/HypotheseCsvExportServiceTest.java b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/HypotheseCsvExportServiceTest.java index 349805af1058ff0598b4d95fa389445a1240f5bc..0e8a555dd124edf043feb6d085b81da0056d5524 100644 --- a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/HypotheseCsvExportServiceTest.java +++ b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/HypotheseCsvExportServiceTest.java @@ -44,8 +44,8 @@ class HypotheseCsvExportServiceTest { @Test void getObjectsToWriteShouldReturnRepositoryFindAll() { var entities = List.of( - TestDataFactory.HypotheseFactory.entity("clé", "0.0","Source"), - TestDataFactory.HypotheseFactory.entity("clé2", "1.0","Source") + TestDataFactory.HypotheseFactory.entity("clé", "0.0", "Source", "exemple de description"), + TestDataFactory.HypotheseFactory.entity("clé2", "1.0", "Source", "exemple de description") ); when(repository.findAll()).thenReturn(entities); @@ -54,27 +54,27 @@ class HypotheseCsvExportServiceTest { @Test void printRecordShouldUseEntityAttributes() throws IOException { - var entity = TestDataFactory.HypotheseFactory.entity("clé", "0.0","Source"); + var entity = TestDataFactory.HypotheseFactory.entity("clé", "0.0", "Source", "exemple de description"); assertDoesNotThrow(() -> exportService.printRecord(csvPrinter, entity)); - Mockito.verify(csvPrinter, times(1)).printRecord(entity.getCode(), entity.getValeur(), entity.getSource()); + Mockito.verify(csvPrinter, times(1)).printRecord(entity.getCode(), entity.getValeur(), entity.getSource(), entity.getDescription()); } @Test - void logRecordErrorShouldLogSpecificErrorForRecord(){ - var entity = TestDataFactory.HypotheseFactory.entity("clé", "0.0","Source"); + void logRecordErrorShouldLogSpecificErrorForRecord() { + var entity = TestDataFactory.HypotheseFactory.entity("clé", "0.0", "Source", "exemple de description"); assertDoesNotThrow(() -> exportService.logRecordError(entity, new Exception("Test"))); } @Test - void logRecordErrorShouldLogGenericErrorForRecord(){ + void logRecordErrorShouldLogGenericErrorForRecord() { assertDoesNotThrow(() -> exportService.logRecordError(null, new Exception("Test"))); } @Test - void logRecordErrorShouldLogGenericErrorForFile(){ + void logRecordErrorShouldLogGenericErrorForFile() { assertDoesNotThrow(() -> exportService.logWriterError(new Exception("Test"))); } @@ -82,7 +82,7 @@ class HypotheseCsvExportServiceTest { void writeToCsvShouldReturnCSV() { // given var entities = List.of( - TestDataFactory.HypotheseFactory.entity("clé", "0.0","Source") + TestDataFactory.HypotheseFactory.entity("clé", "0.0", "Source", "exemple de description") ); when(repository.findAll()).thenReturn(entities); StringWriter stringWriter = new StringWriter(); @@ -93,7 +93,7 @@ class HypotheseCsvExportServiceTest { // Then String result = stringWriter.toString(); assertEquals( - "cle;valeur;source\r\nclé;0.0;Source\r\n", + "cle;valeur;source;description\r\nclé;0.0;Source;exemple de description\r\n", result ); } diff --git a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/ImpactMixElectriqueCsvExportServiceTest.java b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/ImpactMixElectriqueCsvExportServiceTest.java index f079cedeebc1378c6fdb59121a7c7b5d3967be4b..1553433eddd5e0e4bb4a87d672acd432f1d23386 100644 --- a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/ImpactMixElectriqueCsvExportServiceTest.java +++ b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/ImpactMixElectriqueCsvExportServiceTest.java @@ -83,7 +83,6 @@ class ImpactMixElectriqueCsvExportServiceTest { @Test void getObjectsToWriteShouldReturnRepositoryFindAll() { var entities = facteurCaracterisationEntities(); - when(repository.findByNiveauAndCategorie(Constants.MIXELEC_NIVEAU, Constants.MIXELEC_CATEGORIE)).thenReturn(entities); var actual = exportService.getObjectsToWrite(); assertEquals(2, actual.size()); diff --git a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/TypeEquipementCsvExportServiceTest.java b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/TypeEquipementCsvExportServiceTest.java index 2433525aad876db28bc19c054c014b44f0bd884a..47eb4fcf78699fc9510401759381b478cd9d5843 100644 --- a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/TypeEquipementCsvExportServiceTest.java +++ b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/TypeEquipementCsvExportServiceTest.java @@ -8,9 +8,17 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.mte.numecoeval.referentiel.domain.model.TypeEquipement; import org.mte.numecoeval.referentiel.domain.ports.input.impl.ImportTypeEquipementPortImpl; import org.mte.numecoeval.referentiel.factory.TestDataFactory; -import org.mte.numecoeval.referentiel.infrastructure.jpa.repository.TypeEquipementRepository; +import org.mte.numecoeval.referentiel.infrastructure.jpa.entity.TypeEquipementEntity; +import org.mte.numecoeval.referentiel.infrastructure.jpa.entity.TypeItemEntity; +import org.mte.numecoeval.referentiel.infrastructure.jpa.repository.TypeItemRepository; +import org.mte.numecoeval.referentiel.infrastructure.mapper.TypeEquipementMapper; +import org.mte.numecoeval.referentiel.infrastructure.mapper.TypeEquipementMapperImpl; +import org.mte.numecoeval.referentiel.infrastructure.mapper.TypeItemMapper; +import org.mte.numecoeval.referentiel.infrastructure.mapper.TypeItemMapperImpl; +import org.springframework.test.util.ReflectionTestUtils; import java.io.IOException; import java.io.StringWriter; @@ -18,11 +26,13 @@ import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.List; import java.util.Locale; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; +import static org.mte.numecoeval.referentiel.utils.Constants.CATEGORIE_EQUIPEMENT_PHYSIQUE; class TypeEquipementCsvExportServiceTest { @@ -30,7 +40,9 @@ class TypeEquipementCsvExportServiceTest { TypeEquipementCsvExportService exportService; @Mock - TypeEquipementRepository repository; + TypeItemRepository repository; + TypeItemMapper typeItemMapper = new TypeItemMapperImpl(); + TypeEquipementMapper typeEquipementMapper = new TypeEquipementMapperImpl(); @Mock CSVPrinter csvPrinter; @@ -38,6 +50,24 @@ class TypeEquipementCsvExportServiceTest { @BeforeEach void setup() { MockitoAnnotations.openMocks(this); + ReflectionTestUtils.setField(exportService, "typeItemMapper", typeItemMapper); + ReflectionTestUtils.setField(exportService, "typeEquipementMapper", typeEquipementMapper); + } + + private List<TypeItemEntity> typeItemEntities() { + return List.of( + TestDataFactory.TypeItemFactory.entity( + "Serveur", CATEGORIE_EQUIPEMENT_PHYSIQUE, true, null, 6.0, null, "", "Test"), + TestDataFactory.TypeItemFactory.entity( + "Communication Device", CATEGORIE_EQUIPEMENT_PHYSIQUE, false, "commentaires", 4.0, null, "SSG", + "refItem") + ); + } + + private TypeEquipementEntity typeEquipementEntity() { + return TestDataFactory.TypeEquipementFactory.entity( + "Serveur", true, 6.0, "Commentaires", "Test", + "test"); } @Test @@ -47,28 +77,20 @@ class TypeEquipementCsvExportServiceTest { @Test void getObjectsToWriteShouldReturnRepositoryFindAll() { - var entities = List.of( - TestDataFactory.TypeEquipementFactory.entity( - "Serveur", true, 6.0, "", "Test", - "test"), - TestDataFactory.TypeEquipementFactory.entity( - "Ecran", false, 4.0, "", "Test", - "test") - ); - when(repository.findAll()).thenReturn(entities); - - assertEquals(entities, exportService.getObjectsToWrite()); + List<TypeItemEntity> entities = typeItemEntities(); + when(repository.findByCategorie(CATEGORIE_EQUIPEMENT_PHYSIQUE)).thenReturn(entities); + var actual = exportService.getObjectsToWrite(); + assertEquals(2, actual.size()); + assertEquals("Communication Device,Serveur", actual.stream().map(TypeEquipement::getType).sorted().collect(Collectors.joining(","))); } @Test void printRecordShouldUseEntityAttributes() throws IOException { - var entity = TestDataFactory.TypeEquipementFactory.entity( - "Serveur", true, 6.0, "", "Test", - "test"); + var entity = typeEquipementEntity(); DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH)); df.setMaximumFractionDigits(340); - assertDoesNotThrow(() -> exportService.printRecord(csvPrinter, entity)); + assertDoesNotThrow(() -> exportService.printRecord(csvPrinter, typeEquipementMapper.toDomaine(entity))); Mockito.verify(csvPrinter, times(1)).printRecord( entity.getType(), @@ -81,11 +103,8 @@ class TypeEquipementCsvExportServiceTest { @Test void logRecordErrorShouldLogSpecificErrorForRecord() { - var entity = TestDataFactory.TypeEquipementFactory.entity( - "Serveur", true, 6.0, "", "Test", - "test"); - - assertDoesNotThrow(() -> exportService.logRecordError(entity, new Exception("Test"))); + var entity = typeEquipementEntity(); + assertDoesNotThrow(() -> exportService.logRecordError(typeEquipementMapper.toDomaine(entity), new Exception("Test"))); } @Test @@ -101,12 +120,8 @@ class TypeEquipementCsvExportServiceTest { @Test void writeToCsvShouldReturnCSV() { // given - var entities = List.of( - TestDataFactory.TypeEquipementFactory.entity( - "Serveur", true, 6.0, "Commentaires", "Test", - "test") - ); - when(repository.findAll()).thenReturn(entities); + var entities = typeItemEntities(); + when(repository.findByCategorie(CATEGORIE_EQUIPEMENT_PHYSIQUE)).thenReturn(entities); StringWriter stringWriter = new StringWriter(); // when @@ -115,8 +130,12 @@ class TypeEquipementCsvExportServiceTest { // Then String result = stringWriter.toString(); assertEquals( - "type;serveur;commentaire;dureeVieDefaut;source;refEquipementParDefaut\r\nServeur;true;Commentaires;6;Test;test\r\n", - result + """ + type;serveur;commentaire;dureeVieDefaut;source;refEquipementParDefaut + Serveur;true;;6;;Test + Communication Device;false;commentaires;4;SSG;refItem + """, + result.replaceAll("\r\n", "\n") ); } } diff --git a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/TypeItemCsvExportServiceTest.java b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/TypeItemCsvExportServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..1d800d1810b2c4c2e51bcb2e86775469ec32cac2 --- /dev/null +++ b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/adapter/export/TypeItemCsvExportServiceTest.java @@ -0,0 +1,128 @@ +package org.mte.numecoeval.referentiel.infrastructure.adapter.export; + +import org.apache.commons.csv.CSVPrinter; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.mte.numecoeval.referentiel.domain.ports.input.impl.ImportTypeItemPortImpl; +import org.mte.numecoeval.referentiel.factory.TestDataFactory; +import org.mte.numecoeval.referentiel.infrastructure.jpa.repository.TypeItemRepository; + +import java.io.IOException; +import java.io.StringWriter; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.util.List; +import java.util.Locale; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.when; + +class TypeItemCsvExportServiceTest { + + @InjectMocks + TypeItemCsvExportService exportService; + + @Mock + TypeItemRepository repository; + + @Mock + CSVPrinter csvPrinter; + + @BeforeEach + void setup() { + MockitoAnnotations.openMocks(this); + } + + @Test + void getHeadersShouldReturnSameHeadersAsImport() { + Assertions.assertEquals(ImportTypeItemPortImpl.getHeaders(), exportService.getHeaders()); + } + + @Test + void getObjectsToWriteShouldReturnRepositoryFindAll() { + var entities = List.of( + TestDataFactory.TypeItemFactory.entity( + "Serveur", null, true, "Exemple de serveur basique", + 6.0, null, "NegaOctet", "serveur_par_defaut"), + TestDataFactory.TypeItemFactory.entity( + "deplacement voiture hybride", "deplacement_hybride", false, + "Exemple d'opération non it", 50.0, "CONSO_MOYENNE_VOITURE_HYBRIDE", "SSG", "deplacement_voiture_hybride" + ) + ); + when(repository.findAll()).thenReturn(entities); + + assertEquals(entities, exportService.getObjectsToWrite()); + } + + @Test + void printRecordShouldUseEntityAttributes() throws IOException { + var entity = TestDataFactory.TypeItemFactory.entity( + "Serveur", null, true, "Exemple de serveur basique", + 6.0, null, "NegaOctet", "serveur_par_defaut"); + DecimalFormat df = new DecimalFormat("0", DecimalFormatSymbols.getInstance(Locale.ENGLISH)); + df.setMaximumFractionDigits(340); + + assertDoesNotThrow(() -> exportService.printRecord(csvPrinter, entity)); + + Mockito.verify(csvPrinter, times(1)).printRecord( + entity.getType(), + entity.getCategorie(), + entity.isServeur(), + entity.getCommentaire(), + df.format(entity.getDureeVieDefaut()), + entity.getRefHypothese(), + entity.getSource(), + entity.getRefItemParDefaut()); + } + + @Test + void logRecordErrorShouldLogSpecificErrorForRecord() { + var entity = TestDataFactory.TypeItemFactory.entity( + "Serveur", null, true, "Exemple de serveur basique", + 6.0, null, "NegaOctet", "serveur_par_defaut"); + + assertDoesNotThrow(() -> exportService.logRecordError(entity, new Exception("Test"))); + } + + @Test + void logRecordErrorShouldLogGenericErrorForRecord() { + assertDoesNotThrow(() -> exportService.logRecordError(null, new Exception("Test"))); + } + + @Test + void logRecordErrorShouldLogGenericErrorForFile() { + assertDoesNotThrow(() -> exportService.logWriterError(new Exception("Test"))); + } + + @Test + void writeToCsvShouldReturnCSV() { + // given + var entities = List.of( + TestDataFactory.TypeItemFactory.entity( + "Serveur", null, true, "Exemple de serveur basique", + 6.0, null, "NegaOctet", "serveur_par_defaut") + ); + when(repository.findAll()).thenReturn(entities); + StringWriter stringWriter = new StringWriter(); + + // when + exportService.writeToCsv(stringWriter); + + // Then + String result = stringWriter.toString(); + assertEquals( + """ + type;categorie;serveur;commentaire;dureeVieDefaut;refHypothese;source;refItemParDefaut + Serveur;;true;Exemple de serveur basique;6;;NegaOctet;serveur_par_defaut + """, + result.replaceAll("\r\n", "\n") + ); + } +} diff --git a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/jpa/MixElectriqueJpaAdapterTest.java b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/jpa/MixElectriqueJpaAdapterTest.java index f06a4f596029bee7ae713c317a51124b5ecd20ad..e46ae4d4d11b97d6b83232ae29a60834774c43ec 100644 --- a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/jpa/MixElectriqueJpaAdapterTest.java +++ b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/jpa/MixElectriqueJpaAdapterTest.java @@ -23,7 +23,7 @@ import org.mte.numecoeval.referentiel.utils.Constants; import org.springframework.test.util.ReflectionTestUtils; import java.util.Collections; -import java.util.Optional; +import java.util.List; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; @@ -74,8 +74,7 @@ class MixElectriqueJpaAdapterTest { .setPays(PAYS) .setCritere(CRITERE); - Mockito.when(repository.findByNiveauAndCategorieAndLocalisationAndCritere(Constants.MIXELEC_NIVEAU, Constants.MIXELEC_CATEGORIE, wantedId.getPays(), wantedId.getCritere())).thenReturn(Optional.of(expectedEntity)); - + Mockito.when(repository.findByNiveauAndCategorieAndLocalisationAndCritere(Constants.MIXELEC_NIVEAU, Constants.MIXELEC_CATEGORIE, wantedId.getPays(), wantedId.getCritere())).thenReturn(List.of(expectedEntity)); var actualDomain = assertDoesNotThrow(() -> jpaAdapter.get(wantedId)); assertNotNull(actualDomain.getCritere()); @@ -89,7 +88,7 @@ class MixElectriqueJpaAdapterTest { var wantedId = new MixElectriqueId() .setPays("NonExistant") .setCritere("Inexistant"); - Mockito.when(repository.findByNiveauAndCategorieAndLocalisationAndCritere(Constants.MIXELEC_NIVEAU, Constants.MIXELEC_CATEGORIE, wantedId.getPays(), wantedId.getCritere())).thenReturn(Optional.empty()); + Mockito.when(repository.findByNiveauAndCategorieAndLocalisationAndCritere(Constants.MIXELEC_NIVEAU, Constants.MIXELEC_CATEGORIE, wantedId.getPays(), wantedId.getCritere())).thenReturn(Collections.emptyList()); ReferentielException expectedException = assertThrows(ReferentielException.class, () -> jpaAdapter.get(wantedId)); diff --git a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/facteurcaracterisation/ReferentielFacteurCaracterisationRestApiImplTest.java b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/facteurcaracterisation/ReferentielFacteurCaracterisationRestApiImplTest.java index 3a1fd17532c770010e4f10a5b9732abcb43041ff..8fd5ec7e0923d0e9f2f4a95bb9ca47ef7020c672 100644 --- a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/facteurcaracterisation/ReferentielFacteurCaracterisationRestApiImplTest.java +++ b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/facteurcaracterisation/ReferentielFacteurCaracterisationRestApiImplTest.java @@ -5,7 +5,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.mte.numecoeval.referentiel.domain.exception.ReferentielException; import org.mte.numecoeval.referentiel.infrastructure.adapter.export.FacteurCaracterisationCsvExportService; import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.FacteurCaracterisationDTO; -import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.id.FacteurCaracterisationIdDTO; import org.mte.numecoeval.referentiel.infrastructure.restapi.facade.FacteurCaracterisationFacade; import org.mte.numecoeval.referentiel.utils.Constants; import org.springframework.beans.factory.annotation.Autowired; @@ -20,6 +19,7 @@ import org.springframework.web.server.ResponseStatusException; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; +import java.util.List; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @@ -43,36 +43,31 @@ public class ReferentielFacteurCaracterisationRestApiImplTest { String nom = "Ordinateur Portable"; String nomCritere = "Changement Climatique"; String codeEtapeACV = "UTILISATION"; - var idDTO = new FacteurCaracterisationIdDTO(nom, - codeEtapeACV, - nomCritere - ); - var expectedDTO = FacteurCaracterisationDTO.builder() + + var fc = FacteurCaracterisationDTO.builder() .nom(nom) .etape(codeEtapeACV) .critere(nomCritere) .niveau(Constants.EQUIPEMENT_NIVEAU) .valeur(1.0).build(); - when(referentielFacade.get(idDTO)).thenReturn(expectedDTO); + var expectedDTO = List.of(fc); + when(referentielFacade.getByFilters(nomCritere, codeEtapeACV, nom, null, null)).thenReturn(expectedDTO); - var receivedDTO = referentielRestApi.get(nom, nomCritere, codeEtapeACV); - assertSame(receivedDTO, receivedDTO); - verify(referentielFacade).get(idDTO); + var actualDTO = referentielRestApi.get(nomCritere, codeEtapeACV, nom, null, null); + assertSame(expectedDTO, actualDTO); + verify(referentielFacade).getByFilters(nomCritere, codeEtapeACV, nom, null, null); } @Test void get_whenNotFound_thenShouldThrowReferentielException() throws ReferentielException { - String refEquipement = "Ordinateur Portable"; + String nom = "Ordinateur Portable"; String nomCritere = "Changement Climatique"; String codeEtapeACV = "UTILISATION"; - var idDTO = new FacteurCaracterisationIdDTO(refEquipement, - codeEtapeACV, - nomCritere - ); - when(referentielFacade.get(idDTO)).thenThrow(new ReferentielException("Impact Equipement non trouvé")); - var exception = assertThrows(ReferentielException.class, () -> referentielRestApi.get(refEquipement, nomCritere, codeEtapeACV)); + when(referentielFacade.getByFilters(nomCritere, codeEtapeACV, nom, null, null)).thenThrow(new ReferentielException("Impact Equipement non trouvé")); + + var exception = assertThrows(ReferentielException.class, () -> referentielRestApi.get(nomCritere, codeEtapeACV, nom, null, null)); assertEquals("Impact Equipement non trouvé", exception.getMessage()); } @@ -122,7 +117,7 @@ public class ReferentielFacteurCaracterisationRestApiImplTest { assertEquals("text/csv;charset=UTF-8", servletResponse.getContentType()); String headerContentDisposition = servletResponse.getHeader("Content-Disposition"); assertNotNull(headerContentDisposition); - assertTrue(headerContentDisposition.contains("attachment; filename=facteurCaracterisation-")); + assertTrue(headerContentDisposition.contains("attachment; filename=facteursCaracterisation-")); assertEquals(200, servletResponse.getStatus()); } diff --git a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/typeitem/ReferentielTypeItemRestApiImplTest.java b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/typeitem/ReferentielTypeItemRestApiImplTest.java new file mode 100644 index 0000000000000000000000000000000000000000..82f74fa2118fdf7dfba934ed9b30a58e8327ac55 --- /dev/null +++ b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/restapi/controller/typeitem/ReferentielTypeItemRestApiImplTest.java @@ -0,0 +1,115 @@ +package org.mte.numecoeval.referentiel.infrastructure.restapi.controller.typeitem; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mte.numecoeval.referentiel.domain.exception.ReferentielException; +import org.mte.numecoeval.referentiel.factory.TestDataFactory; +import org.mte.numecoeval.referentiel.infrastructure.adapter.export.TypeItemCsvExportService; +import org.mte.numecoeval.referentiel.infrastructure.restapi.dto.TypeItemDTO; +import org.mte.numecoeval.referentiel.infrastructure.restapi.facade.TypeItemFacade; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.HttpStatus; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.web.server.ResponseStatusException; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +@ContextConfiguration(classes = {ReferentielTypeItemRestApiImpl.class}) +@ExtendWith(SpringExtension.class) +class ReferentielTypeItemRestApiImplTest { + @Autowired + private ReferentielTypeItemRestApiImpl referentielRestApi; + + @MockBean + private TypeItemFacade referentielFacade; + + @MockBean + private TypeItemCsvExportService csvExportService; + + @Test + void getAll_shouldCallFacadeGetAllAndReturnAllDTOs() { + ArrayList<TypeItemDTO> typeItemDTOS = new ArrayList<>(); + when(referentielFacade.getAllTypesItem()).thenReturn(typeItemDTOS); + + List<TypeItemDTO> actualAll = referentielRestApi.getTypesItem(); + + assertSame(typeItemDTOS, actualAll); + assertTrue(actualAll.isEmpty()); + verify(referentielFacade).getAllTypesItem(); + } + + @Test + void getTypeItem_shouldCallFacadeGetAndReturnDTO() throws ReferentielException { + + String expectedType = "Serveur"; + TypeItemDTO expectedDTO = TestDataFactory.TypeItemFactory.dto(expectedType, null, true, "Exemple de serveur basique", + 6.0, null, "NegaOctet", "serveur_par_defaut"); + when(referentielFacade.getTypeItemForType(expectedType)).thenReturn(expectedDTO); + + TypeItemDTO actualResponse = referentielRestApi.getTypeItem(expectedType); + + assertSame(expectedDTO, actualResponse); + verify(referentielFacade).getTypeItemForType(expectedType); + } + + @Test + void importCSV_shouldCallPurgeAndAddAll() throws IOException, ReferentielException { + doNothing().when(referentielFacade).purgeAndAddAll(any()); + + referentielRestApi.importCSV(new MockMultipartFile("Name", "AAAAAAAA".getBytes(StandardCharsets.UTF_8))); + + verify(referentielFacade).purgeAndAddAll(any()); + } + + @Test + void importCSV_whenEmptyFileThenShouldThrowException() throws ReferentielException { + doNothing().when(referentielFacade).purgeAndAddAll(any()); + MockMultipartFile file = new MockMultipartFile("Name", (byte[]) null); + + ResponseStatusException responseStatusException = assertThrows( + ResponseStatusException.class, + () -> referentielRestApi.importCSV(file) + ); + + assertEquals(HttpStatus.BAD_REQUEST, responseStatusException.getStatusCode()); + assertEquals("Le fichier n'existe pas ou alors il est vide", responseStatusException.getReason()); + } + + @Test + void importCSV_whenNullFileThenShouldThrowException() throws ReferentielException { + doNothing().when(referentielFacade).purgeAndAddAll(any()); + + ResponseStatusException responseStatusException = assertThrows( + ResponseStatusException.class, + () -> referentielRestApi.importCSV(null) + ); + + assertEquals(HttpStatus.BAD_REQUEST, responseStatusException.getStatusCode()); + assertEquals("Le fichier n'existe pas ou alors il est vide", responseStatusException.getReason()); + } + + @Test + void exportCSV_shouldReturnCSVFile() { + var servletResponse = new MockHttpServletResponse(); + + assertDoesNotThrow(() -> referentielRestApi.exportCSV(servletResponse)); + + assertEquals("text/csv;charset=UTF-8", servletResponse.getContentType()); + String headerContentDisposition = servletResponse.getHeader("Content-Disposition"); + assertNotNull(headerContentDisposition); + assertTrue(headerContentDisposition.contains("attachment; filename=typeItem-")); + assertEquals(200, servletResponse.getStatus()); + + } +} diff --git a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/restapi/facade/HypotheseFacadeTest.java b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/restapi/facade/HypotheseFacadeTest.java index 8e40c311bcdb9ca408a4d61c9a58bf9747920e42..1fea959937cc93c35e017dee9c282e711c3a9a15 100644 --- a/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/restapi/facade/HypotheseFacadeTest.java +++ b/services/api-referentiel/src/test/java/org/mte/numecoeval/referentiel/infrastructure/restapi/facade/HypotheseFacadeTest.java @@ -2,11 +2,7 @@ package org.mte.numecoeval.referentiel.infrastructure.restapi.facade; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.*; import org.mte.numecoeval.referentiel.domain.exception.ReferentielException; import org.mte.numecoeval.referentiel.domain.model.Hypothese; import org.mte.numecoeval.referentiel.domain.model.id.HypotheseId; @@ -41,7 +37,7 @@ class HypotheseFacadeTest { void get_shouldReturnMatchingDTO() throws ReferentielException { var wantedDTOId = TestDataFactory.HypotheseFactory.idDTO("code"); var expectedDomainID = TestDataFactory.HypotheseFactory.idDomain("code"); - var expectedDomain = TestDataFactory.HypotheseFactory.domain("code", "1.1", "Test"); + var expectedDomain = TestDataFactory.HypotheseFactory.domain("code", "1.1", "Test", "exemple de description"); Mockito.when(persistencePort.get(expectedDomainID)).thenReturn(expectedDomain); @@ -55,17 +51,17 @@ class HypotheseFacadeTest { @Test void getAll_ShouldAllReturnMatchingDTO() { var expectedDomains = Arrays.asList( - TestDataFactory.HypotheseFactory.domain("code", "2.0", "Test"), - TestDataFactory.HypotheseFactory.domain("code2", "3.0", "Test") + TestDataFactory.HypotheseFactory.domain("code", "2.0", "Test", "exemple de description"), + TestDataFactory.HypotheseFactory.domain("code2", "3.0", "Test", "exemple de description") ); Mockito.when(persistencePort.getAll()).thenReturn(expectedDomains); - var result = assertDoesNotThrow( () -> facadeToTest.getAll() ); + var result = assertDoesNotThrow(() -> facadeToTest.getAll()); assertEquals(expectedDomains.size(), result.size()); - expectedDomains.forEach( expectedDomain -> { + expectedDomains.forEach(expectedDomain -> { var matchingDTO = result.stream() .filter(critereDTO -> expectedDomain.getCode().equals(critereDTO.getCode())) .findAny(); @@ -82,8 +78,8 @@ class HypotheseFacadeTest { @Test void purgeAndAddAll_ShouldCallPurgeThenSaveAll() throws ReferentielException { var dtosToSave = Arrays.asList( - TestDataFactory.HypotheseFactory.dto("hyp", "1.0", "Test"), - TestDataFactory.HypotheseFactory.dto("hyp2", "m3", "Autre Test") + TestDataFactory.HypotheseFactory.dto("hyp", "1.0", "Test", "exemple de description"), + TestDataFactory.HypotheseFactory.dto("hyp2", "m3", "Autre Test", "exemple de description") ); ArgumentCaptor<Collection<Hypothese>> valueCapture = ArgumentCaptor.forClass(Collection.class); diff --git a/services/api-referentiel/src/test/resources/csv/unit/hypothese.csv b/services/api-referentiel/src/test/resources/csv/unit/hypothese.csv index a1a6b28614a66c174a8d3e58047a24c3dfa46a90..4093f137d0cbd94d4f21de122f35e37bd84bb5f0 100644 --- a/services/api-referentiel/src/test/resources/csv/unit/hypothese.csv +++ b/services/api-referentiel/src/test/resources/csv/unit/hypothese.csv @@ -1,3 +1,3 @@ -cle;valeur;source -PUEPardDfault;1.6;expertise IJO -DureeVieServeurParDefaut;3;US 46 +cle;valeur;source;description +PUEPardDfault;1.6;expertise IJO; +DureeVieServeurParDefaut;3;US 46;unité: années diff --git a/services/api-referentiel/src/test/resources/csv/unit/hypothese_errorInMiddle.csv b/services/api-referentiel/src/test/resources/csv/unit/hypothese_errorInMiddle.csv index 66f419ba89de4a72df7b2341bce92633b44f34dd..b4a98ebda2b87f76584eebc9133d1b207783c7df 100644 --- a/services/api-referentiel/src/test/resources/csv/unit/hypothese_errorInMiddle.csv +++ b/services/api-referentiel/src/test/resources/csv/unit/hypothese_errorInMiddle.csv @@ -1,5 +1,5 @@ -cle;valeur;source -PUEPardDfault;1.6;expertise IJO -;PasUnChiffreMaisPasGrave;Test;Pas;Le;Bon;Nombre;De;Colonne -ErreurValeur;;Test;Pas;Le;Bon;Nombre;De;Colonne -DureeVieServeurParDefaut;3;US 46 +cle;valeur;source;description +PUEPardDfault;1.6;expertise IJO; +;PasUnChiffreMaisPasGrave;Test;Pas;Le;Bon;Nombre;De;Colonne; +ErreurValeur;;Test;Pas;Le;Bon;Nombre;De;Colonne; +DureeVieServeurParDefaut;3;US 46;unité: années \ No newline at end of file diff --git a/services/api-referentiel/src/test/resources/csv/unit/typeItem.csv b/services/api-referentiel/src/test/resources/csv/unit/typeItem.csv new file mode 100644 index 0000000000000000000000000000000000000000..f96c37285188c75bee2e5495bc1b73b29f74dd2d --- /dev/null +++ b/services/api-referentiel/src/test/resources/csv/unit/typeItem.csv @@ -0,0 +1,3 @@ +type;categorie;serveur;commentaire;dureeVieDefaut;refHypothese;source;refItemParDefaut +Serveur;;true;Exemple de serveur basique;6.0;;NegaOctet;serveur_par_defaut +deplacement voiture hybride;deplacement_hybride;false;Exemple d'opération non it;50.0;CONSO_MOYENNE_VOITURE_HYBRIDE;SSG;deplacement_voiture_hybride diff --git a/services/api-referentiel/src/test/resources/csv/unit/typeItem_errorInMiddle.csv b/services/api-referentiel/src/test/resources/csv/unit/typeItem_errorInMiddle.csv new file mode 100644 index 0000000000000000000000000000000000000000..e690069c2d67ed3b32e6938bc0d31aadc1055458 --- /dev/null +++ b/services/api-referentiel/src/test/resources/csv/unit/typeItem_errorInMiddle.csv @@ -0,0 +1,4 @@ +type;categorie;serveur;commentaire;dureeVieDefaut;refHypothese;source;refItemParDefaut +Serveur;;true;Exemple de serveur basique;6.0;;NegaOctet;serveur_par_defaut +;;TypeAbsent;"est une erreur";complete;"Sur toute";"La";"Ligne"; +deplacement voiture hybride;deplacement_hybride;false;Exemple d'opération non it;50.0;CONSO_MOYENNE_VOITURE_HYBRIDE;SSG;deplacement_voiture_hybride \ No newline at end of file diff --git a/services/calculs/pom.xml b/services/calculs/pom.xml index ada4101577ed18a0afb60b68c0b68db390e7cf53..f9949cac03a25531dcca20fcedbf766c1ed3c075 100644 --- a/services/calculs/pom.xml +++ b/services/calculs/pom.xml @@ -5,11 +5,11 @@ <parent> <groupId>org.mte.numecoeval</groupId> <artifactId>core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <artifactId>calculs</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> <name>calculs</name> <description>Module contenant l'intégralité des règles de calculs et du code métier lié aux calculs d'impact d'équipement diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/demande/DemandeCalculImpactEquipementPhysique.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/demande/DemandeCalculImpactEquipementPhysique.java index 4e4247f964a5d4ced269f7defbaa65ab402926e3..6c0da70ed89125cb7e070a24004add2322b0da59 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/demande/DemandeCalculImpactEquipementPhysique.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/demande/DemandeCalculImpactEquipementPhysique.java @@ -36,6 +36,8 @@ public class DemandeCalculImpactEquipementPhysique { List<ReferentielMixElectrique> mixElectriques; + OptionsCalcul optionsCalcul; + public Optional<ReferentielHypothese> getHypotheseFromCode(String code) { if (code == null || hypotheses == null) { return Optional.empty(); diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/demande/DemandeCalculImpactOperationNonIT.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/demande/DemandeCalculImpactOperationNonIT.java new file mode 100644 index 0000000000000000000000000000000000000000..746d364850e01523509e3406e671c0e21fde79c1 --- /dev/null +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/demande/DemandeCalculImpactOperationNonIT.java @@ -0,0 +1,85 @@ +package org.mte.numecoeval.calculs.domain.data.demande; + +import lombok.*; +import org.mte.numecoeval.calculs.domain.data.entree.OperationNonIT; +import org.mte.numecoeval.calculs.domain.data.referentiel.*; +import org.mte.numecoeval.calculs.domain.utils.Constants; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import static org.mte.numecoeval.calculs.domain.utils.Constants.CATEGORIES_INDIRECT_FABRICATION; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +public class DemandeCalculImpactOperationNonIT { + + LocalDateTime dateCalcul; + + OperationNonIT operationNonIT; + + ReferentielEtapeACV etape; + + ReferentielCritere critere; + + ReferentielTypeItem typeItem; + + List<ReferentielHypothese> hypotheses; + + List<ReferentielFacteurCaracterisation> facteurCaracterisations; + + public Optional<ReferentielHypothese> getHypotheseFromCode(String code) { + if (code == null || hypotheses == null) { + return Optional.empty(); + } + + return hypotheses.stream() + .filter(hypothese -> code.equals(hypothese.getCode())) + .findFirst(); + } + + public Optional<ReferentielFacteurCaracterisation> getFacteurCaracterisation(String refItem) { + if (refItem == null || facteurCaracterisations == null) { + return Optional.empty(); + } + if (CATEGORIES_INDIRECT_FABRICATION.contains(typeItem.getCategorie())) { + return facteurCaracterisations.stream() + .filter(Objects::nonNull) + .filter(facteurCaracterisation -> refItem.equals(facteurCaracterisation.getNom()) + && critere.getNomCritere().equals(facteurCaracterisation.getCritere()) + && "FABRICATION".equals(facteurCaracterisation.getEtape()) + ) + .findFirst(); + } + return facteurCaracterisations.stream() + .filter(Objects::nonNull) + .filter(facteurCaracterisation -> refItem.equals(facteurCaracterisation.getNom()) + && critere.getNomCritere().equals(facteurCaracterisation.getCritere()) + && etape.getCode().equals(facteurCaracterisation.getEtape()) + ) + .findFirst(); + } + + public Optional<ReferentielFacteurCaracterisation> getMixElectriqueFromFacteurCaracterisation(String localisation) { + if (localisation == null || facteurCaracterisations == null) { + return Optional.empty(); + } + return facteurCaracterisations.stream() + .filter(Objects::nonNull) + .filter(fc -> Constants.ELECTRICITY_MIX_CATEGORY.equals(fc.getCategorie()) && + localisation.equals(fc.getLocalisation())) + .findFirst(); + } + + public String getRefItemParDefaut() { + if (typeItem != null) { + return typeItem.getRefItemParDefaut(); + } + return null; + } +} diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/demande/MetadataCalcul.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/demande/MetadataCalcul.java new file mode 100644 index 0000000000000000000000000000000000000000..db3d15aa9c969e3663c0ab0cd9d3cc8af6617047 --- /dev/null +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/demande/MetadataCalcul.java @@ -0,0 +1,7 @@ +package org.mte.numecoeval.calculs.domain.data.demande; + +import org.mte.numecoeval.calculs.domain.data.trace.TraceCalculImpactOperationNonIT; + +public record MetadataCalcul(double valeurImpactUnitaire, + TraceCalculImpactOperationNonIT traceCalculImpactOperationNonIT) { +} \ No newline at end of file diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/demande/OptionsCalcul.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/demande/OptionsCalcul.java new file mode 100644 index 0000000000000000000000000000000000000000..bee2bb2f7aed4277af29ecbb08617ce853100660 --- /dev/null +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/demande/OptionsCalcul.java @@ -0,0 +1,5 @@ +package org.mte.numecoeval.calculs.domain.data.demande; + +public record OptionsCalcul(String dureeUsage) { + +} diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/Application.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/Application.java index 74624e548f6092dbd2615fd7ed336ac4cb175bea..dfb8e8642afe314e9a2340736b14e441cea8abd3 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/Application.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/Application.java @@ -8,17 +8,18 @@ import java.time.LocalDate; @Data @Builder public class Application { - private String nomApplication; - private String typeEnvironnement; - private String nomEquipementVirtuel; - private String nomSourceDonneeEquipementVirtuel; + private String nomApplication; + private String typeEnvironnement; + private String nomEquipementVirtuel; + private String nomSourceDonneeEquipementVirtuel; - private String nomEquipementPhysique; - private String domaine; - private String sousDomaine; - private String nomLot; - private LocalDate dateLot; - private String nomOrganisation; - private String nomEntite; - private String nomSourceDonnee; + private String nomEquipementPhysique; + private String domaine; + private String sousDomaine; + private String nomLot; + private LocalDate dateLot; + private String nomOrganisation; + private String nomEntite; + private String nomSourceDonnee; + private String qualite; } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/DataCenter.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/DataCenter.java index 482552781c5a0a9406fa9c3b32a38fd4d3ea3635..ace69d69f980d0d989f06c57a9bdac8f0bf48984 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/DataCenter.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/DataCenter.java @@ -9,13 +9,14 @@ import java.time.LocalDate; @Builder public class DataCenter { - private String nomCourtDatacenter; - private String nomLongDatacenter; - private Double pue; - private String localisation; - private String nomLot; - private LocalDate dateLot; - private String nomOrganisation; - private String nomEntite; - private String nomSourceDonnee; + private String nomCourtDatacenter; + private String nomLongDatacenter; + private Double pue; + private String localisation; + private String nomLot; + private LocalDate dateLot; + private String nomOrganisation; + private String nomEntite; + private String nomSourceDonnee; + private String qualite; } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/EquipementPhysique.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/EquipementPhysique.java index 5a054b521bdca26b1c432d0791ffb02230c6d67c..02376c96d42f20d50e6a1e96f9c41008d03c51bc 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/EquipementPhysique.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/EquipementPhysique.java @@ -18,6 +18,9 @@ public class EquipementPhysique { private String utilisateur; private LocalDate dateAchat; private LocalDate dateRetrait; + private Double dureeUsageInterne; + private Double dureeUsageAmont; + private Double dureeUsageAval; private Double quantite; private Float goTelecharge; private Double nbJourUtiliseAn; @@ -36,4 +39,5 @@ public class EquipementPhysique { private Integer nbTotalVCPU; private String modeUtilisation; private Double tauxUtilisation; + private String qualite; } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/EquipementVirtuel.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/EquipementVirtuel.java index dad80c1a27a19dee0a200abb12bcc5a9fd59e191..6b9efa6f17b5545edba18923cb6f98ed2aebe6e9 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/EquipementVirtuel.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/EquipementVirtuel.java @@ -9,19 +9,20 @@ import java.time.LocalDate; @Data @Builder public class EquipementVirtuel { - private Long id; - private String nomEquipementVirtuel; - private String nomEquipementPhysique; - private String nomSourceDonneeEquipementPhysique; - private Integer vCPU; - private String cluster; - private String nomLot; - private LocalDate dateLot; - private String nomOrganisation; - private String nomEntite; - private String nomSourceDonnee; - private Double consoElecAnnuelle; - private String typeEqv; - private Double capaciteStockage; - private Double cleRepartition; + private Long id; + private String nomEquipementVirtuel; + private String nomEquipementPhysique; + private String nomSourceDonneeEquipementPhysique; + private Integer vCPU; + private String cluster; + private String nomLot; + private LocalDate dateLot; + private String nomOrganisation; + private String nomEntite; + private String nomSourceDonnee; + private Double consoElecAnnuelle; + private String typeEqv; + private Double capaciteStockage; + private Double cleRepartition; + private String qualite; } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/OperationNonIT.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/OperationNonIT.java new file mode 100644 index 0000000000000000000000000000000000000000..0c9f54e286ea5ea6195d38456cd65f3a6c178039 --- /dev/null +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/entree/OperationNonIT.java @@ -0,0 +1,28 @@ +package org.mte.numecoeval.calculs.domain.data.entree; + +import lombok.*; + +import java.time.LocalDate; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +public class OperationNonIT { + private String nomItemNonIT; + private Double quantite; + private String type; + private Double dureeDeVie; + private String localisation; + private String nomEntite; + private String nomCourtDatacenter; + private String description; + private Double consoElecAnnuelle; + private String nomLot; + private LocalDate dateLot; + private String nomOrganisation; + private String nomSourceDonnee; + private String statut; + private String qualite; +} diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactApplication.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactApplication.java index 7f6152589735ee740aaa8a4f1ac8b6553d07e843..37eac6078b8cf227d7c9a181909eb2843170576b 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactApplication.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactApplication.java @@ -35,4 +35,5 @@ public class ImpactApplication { Double impactUnitaire; Double consoElecMoyenne; Long idEntree; + String qualite; } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactEquipementPhysique.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactEquipementPhysique.java index 610d6bd2d194b01d38e7934594fe697e6ec85d4c..84ef4b302bbb160e83644c87d42be31f5ed5ef19 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactEquipementPhysique.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactEquipementPhysique.java @@ -33,4 +33,5 @@ public class ImpactEquipementPhysique { Double consoElecMoyenne; Double quantite; String statutEquipementPhysique; + String qualite; } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactEquipementVirtuel.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactEquipementVirtuel.java index 03965dc478515c30813ab101e9290b0b2468bf3a..9eae4a74f522245d9f40005c7a033d02d61521c8 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactEquipementVirtuel.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactEquipementVirtuel.java @@ -32,4 +32,5 @@ public class ImpactEquipementVirtuel { Double impactUnitaire; Double consoElecMoyenne; Long idEntree; + String qualite; } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactOperationNonIT.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactOperationNonIT.java new file mode 100644 index 0000000000000000000000000000000000000000..2177daec37b6cb004e8f68b69948520edcd714de --- /dev/null +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactOperationNonIT.java @@ -0,0 +1,36 @@ +package org.mte.numecoeval.calculs.domain.data.indicateurs; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Builder +@AllArgsConstructor +@Getter +@Setter +public class ImpactOperationNonIT { + LocalDateTime dateCalcul; + String versionCalcul; + String etapeACV; + String critere; + String source; + String statutIndicateur; + String trace; + String nomLot; + LocalDate dateLot; + String unite; + String nomOrganisation; + String nomEntite; + String nomSourceDonnee; + String reference; + String nomItemNonIT; + String typeItem; + Double impactUnitaire; + Double consoElecMoyenne; + Double quantite; + String qualite; +} diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactReseau.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactReseau.java index b439f953b01e5a569351531bc6e7202cb3086687..5922d030f5783bf42d2bc7c660618dd22b30f922 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactReseau.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/indicateurs/ImpactReseau.java @@ -31,5 +31,4 @@ public class ImpactReseau { String unite; Double impactUnitaire; String reference; - } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielCritere.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielCritere.java index 20969e5659b259d9119c2fed8f7fd541e5e33ed5..770b1a7e40583de558f6a3d54c33b7a2c6df5ee8 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielCritere.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielCritere.java @@ -1,10 +1,12 @@ package org.mte.numecoeval.calculs.domain.data.referentiel; -import lombok.Builder; -import lombok.Data; +import lombok.*; @Builder -@Data +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter public class ReferentielCritere { String nomCritere; String unite; diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielEtapeACV.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielEtapeACV.java index 9e42c59578ccf75c0eb96b00407d831a63608f38..bd09a0cb89ac95c0a2c2e6acc944fa3bb4db6b40 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielEtapeACV.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielEtapeACV.java @@ -1,12 +1,13 @@ package org.mte.numecoeval.calculs.domain.data.referentiel; -import lombok.Builder; -import lombok.Data; +import lombok.*; @Builder -@Data +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter public class ReferentielEtapeACV { String code; String libelle; - } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielFacteurCaracterisation.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielFacteurCaracterisation.java new file mode 100644 index 0000000000000000000000000000000000000000..8eaddbf9551318081e78c3b676a413fa6c21de10 --- /dev/null +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielFacteurCaracterisation.java @@ -0,0 +1,23 @@ +package org.mte.numecoeval.calculs.domain.data.referentiel; + +import lombok.*; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +public class ReferentielFacteurCaracterisation { + String nom; + String etape; + String critere; + String description; + String niveau; + String tiers; + String categorie; + Double consoElecMoyenne; + String localisation; + Double valeur; + String unite; + String source; +} diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielHypothese.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielHypothese.java index 351db7d66d9947e2ac313724bf41f43e823a7507..916a02728c277971731c0111033f7e0532c0bbd1 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielHypothese.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielHypothese.java @@ -1,11 +1,13 @@ package org.mte.numecoeval.calculs.domain.data.referentiel; -import lombok.Builder; -import lombok.Data; +import lombok.*; -@Data @Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter public class ReferentielHypothese { private String code; diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielTypeItem.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielTypeItem.java new file mode 100644 index 0000000000000000000000000000000000000000..88b6e4d013dc0876eeb1cb7bdf5fab8c248da1cd --- /dev/null +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/referentiel/ReferentielTypeItem.java @@ -0,0 +1,26 @@ +package org.mte.numecoeval.calculs.domain.data.referentiel; + +import lombok.*; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +public class ReferentielTypeItem { + String type; + + String categorie; + + Boolean serveur; + + String commentaire; + + Double dureeVieDefaut; + + String refHypothese; + + String refItemParDefaut; + + String source; +} diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/ConsoElecAnMoyenne.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/ConsoElecAnMoyenne.java index fc99e3b335011d4d6505df09d9031f0884f2ee23..de0d6c5f0d0a89d4cd33288fd127b4195afe8795 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/ConsoElecAnMoyenne.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/ConsoElecAnMoyenne.java @@ -9,7 +9,7 @@ import lombok.Data; @JsonInclude(JsonInclude.Include.NON_NULL) public class ConsoElecAnMoyenne { private Double valeur; - private Double valeurEquipementConsoElecAnnuelle; + private Double valeurItemConsoElecAnnuelle; private Double valeurReferentielConsoElecMoyenne; - private String sourceReferentielImpactEquipement; + private String sourceReferentielFacteurCaracterisation; } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/DureeDeVie.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/DureeDeVie.java index 1697802d26401dc1ea96a00c489736255873adfa..c4d27f82068a1f22993645827b3ed155ddc6828c 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/DureeDeVie.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/DureeDeVie.java @@ -8,7 +8,11 @@ import lombok.Data; @Builder @JsonInclude(JsonInclude.Include.NON_NULL) public class DureeDeVie { - private Double valeur; + private Double valeurRetenue; + private String methodeDureeUsage; + private Double dureeUsageInterne; + private Double dureeUsageAmont; + private Double dureeUsageAval; private String dateAchat; private String dateRetrait; private DureeDeVieParDefaut dureeDeVieParDefaut; diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/DureeDeVieParDefaut.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/DureeDeVieParDefaut.java index bb046fc9dabf3a04fd721242479f381e525fe352..ca182aaed29a27b5bd0ab88c1988c511605294ac 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/DureeDeVieParDefaut.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/DureeDeVieParDefaut.java @@ -8,8 +8,9 @@ import lombok.Data; @Builder @JsonInclude(JsonInclude.Include.NON_NULL) public class DureeDeVieParDefaut { - private Double valeur; - private Double valeurEquipementDureeVieDefaut; + private Double valeur; + private Double valeurTypeItemDureeVieDefaut; + private String sourceTypeItemDureeVieDefaut; private Double valeurReferentielHypothese; private String sourceReferentielHypothese; } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/Hypothese.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/Hypothese.java new file mode 100644 index 0000000000000000000000000000000000000000..076f2b762f63650a93b49c7095210525445af646 --- /dev/null +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/Hypothese.java @@ -0,0 +1,14 @@ +package org.mte.numecoeval.calculs.domain.data.trace; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Hypothese { + private Double valeur; + private String nom_hypothese; + private String source; +} diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/MixElectrique.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/MixElectrique.java index 5f6e0e459f790242b1391067eae37902067ac2a8..41b191a874687a129ac47d9a939d1f95dad34413 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/MixElectrique.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/MixElectrique.java @@ -13,4 +13,5 @@ public class MixElectrique { private Double dataCenterPue; private Double valeurReferentielMixElectrique; private String sourceReferentielMixElectrique; + } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/TraceCalculImpactOperationNonIT.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/TraceCalculImpactOperationNonIT.java new file mode 100644 index 0000000000000000000000000000000000000000..116a74ad77cbcd8de9216e132ae8e2c35d7b82c0 --- /dev/null +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/data/trace/TraceCalculImpactOperationNonIT.java @@ -0,0 +1,19 @@ +package org.mte.numecoeval.calculs.domain.data.trace; + +import com.fasterxml.jackson.annotation.JsonInclude; +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +@JsonInclude(JsonInclude.Include.NON_NULL) +public class TraceCalculImpactOperationNonIT { + private String formule; + private ConsoElecAnMoyenne consoElecAnMoyenne; + private MixElectrique mixElectrique; + private Double valeurReferentielFacteurCaracterisation; + private String sourceReferentielFacteurCaracterisation; + private Hypothese hypothese; + private DureeDeVie dureeDeVie; + private String erreur; +} diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/CalculImpactOperationNonITService.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/CalculImpactOperationNonITService.java new file mode 100644 index 0000000000000000000000000000000000000000..b78d55ffeee5ca2d1b9b69690dc47b51c0ae5ad0 --- /dev/null +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/CalculImpactOperationNonITService.java @@ -0,0 +1,14 @@ +package org.mte.numecoeval.calculs.domain.port.input.service; + +import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactOperationNonIT; +import org.mte.numecoeval.calculs.domain.data.indicateurs.ImpactOperationNonIT; +import org.mte.numecoeval.calculs.domain.data.trace.DureeDeVie; +import org.mte.numecoeval.calculs.domain.exception.CalculImpactException; + +public interface CalculImpactOperationNonITService { + + ImpactOperationNonIT calculerImpactOperationNonIT(DemandeCalculImpactOperationNonIT demandeCalcul); + + DureeDeVie getDureeVie(DemandeCalculImpactOperationNonIT demandeCalcul) throws CalculImpactException; + +} diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactApplicationServiceImpl.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactApplicationServiceImpl.java index d2ff97428a7bbf4f85bfd9f5686905a611ce8f43..f4da1f2fb91c9f4a79baf1d9889a2d54219be870 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactApplicationServiceImpl.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactApplicationServiceImpl.java @@ -1,6 +1,5 @@ package org.mte.numecoeval.calculs.domain.port.input.service.impl; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactApplication; @@ -18,8 +17,6 @@ public class CalculImpactApplicationServiceImpl implements CalculImpactApplicati private static final String VERSION_CALCUL = "1.1"; - private ObjectMapper objectMapper; - @Override public ImpactApplication calculImpactApplicatif(DemandeCalculImpactApplication demandeCalcul) { ImpactApplication impactErreur; @@ -60,7 +57,7 @@ public class CalculImpactApplicationServiceImpl implements CalculImpactApplicati .etapeACV(demandeCalcul.getImpactEquipementVirtuel().getEtapeACV()) .critere(demandeCalcul.getImpactEquipementVirtuel().getCritere()) .statutIndicateur("ERREUR") - .trace(TraceUtils.getTraceFromTraceur(objectMapper, TraceCalculImpactVirtuelUtils.buildTraceErreur(exception))) + .trace(TraceUtils.getTraceFromTraceur(TraceCalculImpactVirtuelUtils.buildTraceErreur(exception))) .nomLot(demandeCalcul.getApplication().getNomLot()) .nomSourceDonnee(demandeCalcul.getApplication().getNomSourceDonnee()) .dateLot(demandeCalcul.getApplication().getDateLot()) @@ -75,6 +72,7 @@ public class CalculImpactApplicationServiceImpl implements CalculImpactApplicati .sousDomaine(demandeCalcul.getApplication().getSousDomaine()) .impactUnitaire(null) .consoElecMoyenne(null) + .qualite(demandeCalcul.getApplication().getQualite()) .build(); } @@ -117,9 +115,10 @@ public class CalculImpactApplicationServiceImpl implements CalculImpactApplicati .dateLot(demandeCalcul.getApplication().getDateLot()) .versionCalcul(VERSION_CALCUL) .statutIndicateur("OK") - .trace(TraceUtils.getTraceFromTraceur(objectMapper, TraceCalculImpactApplicationUtils.buildTrace(demandeCalcul))) + .trace(TraceUtils.getTraceFromTraceur(TraceCalculImpactApplicationUtils.buildTrace(demandeCalcul))) .impactUnitaire(resultCalcul.valeurImpact) .consoElecMoyenne(resultCalcul.consoElecMoyenne) + .qualite(demandeCalcul.getApplication().getQualite()) .build(); } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactEquipementPhysiqueServiceImpl.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactEquipementPhysiqueServiceImpl.java index 3dcdfe0a167e67091853e653241ba500a778fd71..27b32aa92ebd44bd543f855aff8f1cf6d1b528e6 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactEquipementPhysiqueServiceImpl.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactEquipementPhysiqueServiceImpl.java @@ -1,6 +1,5 @@ package org.mte.numecoeval.calculs.domain.port.input.service.impl; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -24,14 +23,11 @@ import java.util.stream.Collectors; @Slf4j @AllArgsConstructor public class CalculImpactEquipementPhysiqueServiceImpl implements CalculImpactEquipementPhysiqueService { - private static final String VERSION_CALCUL = "1.0"; public static final String NB_JOUR_UTILISE_PAR_DEFAUT = "NbJourUtiliseParDefaut"; public static final String ERREUR_DE_CALCUL_IMPACT_EQUIPEMENT_MESSAGE = "Erreur de calcul impact équipement: Type: {}, Cause: {}, Etape: {}, Critere: {}, Equipement Physique: {}, RefEquipementRetenu: {}, RefEquipementParDefaut: {}"; private final DureeDeVieEquipementPhysiqueService dureeDeVieEquipementPhysiqueService; - private final ObjectMapper objectMapper; - public ImpactEquipementPhysique calculerImpactEquipementPhysique(DemandeCalculImpactEquipementPhysique demandeCalcul) { log.debug("Début de calcul d'impact d'équipement physique : {}, {}, {} ", @@ -81,8 +77,8 @@ public class CalculImpactEquipementPhysiqueServiceImpl implements CalculImpactEq var valeurReferentiel = referentielImpactEquipement.getValeur(); valeurImpactUnitaire = quantite * valeurReferentiel * tauxUtilisationEqPhysique; DureeDeVie dureeVie = dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul); - if (dureeVie != null && dureeVie.getValeur() != null && dureeVie.getValeur() > 0) { - var valeurDureeVie = dureeVie.getValeur(); + if (dureeVie != null && dureeVie.getValeurRetenue() != null && dureeVie.getValeurRetenue() > 0) { + var valeurDureeVie = dureeVie.getValeurRetenue(); valeurImpactUnitaire = valeurImpactUnitaire / valeurDureeVie; traceCalculImpactEquipementPhysique = TraceCalculImpactEquipementPhysiqueUtils.buildTraceSecondScenario(quantite, valeurReferentiel, referentielImpactEquipement.getSource(), dureeVie, tauxUtilisationEqPhysique); } else { @@ -94,7 +90,7 @@ public class CalculImpactEquipementPhysiqueServiceImpl implements CalculImpactEq } var calcul = buildCalculImpactEquipementPhysique(demandeCalcul, valeurImpactUnitaire, consoElecMoyenne); - calcul.setTrace(TraceUtils.getTraceFromTraceur(objectMapper, traceCalculImpactEquipementPhysique)); + calcul.setTrace(TraceUtils.getTraceFromTraceur(traceCalculImpactEquipementPhysique)); return calcul; } @@ -135,6 +131,7 @@ public class CalculImpactEquipementPhysiqueServiceImpl implements CalculImpactEq .dateLot(demandeCalcul.getEquipementPhysique().getDateLot()) .nomEntite(demandeCalcul.getEquipementPhysique().getNomEntite()) .nomOrganisation(demandeCalcul.getEquipementPhysique().getNomOrganisation()) + .qualite(demandeCalcul.getEquipementPhysique().getQualite()) .build(); } @@ -159,7 +156,8 @@ public class CalculImpactEquipementPhysiqueServiceImpl implements CalculImpactEq .dateLot(demandeCalcul.getEquipementPhysique().getDateLot()) .nomEntite(demandeCalcul.getEquipementPhysique().getNomEntite()) .nomOrganisation(demandeCalcul.getEquipementPhysique().getNomOrganisation()) - .trace(TraceUtils.getTraceFromTraceur(objectMapper, TraceCalculImpactEquipementPhysiqueUtils.buildTraceErreur(exception))) + .qualite(demandeCalcul.getEquipementPhysique().getQualite()) + .trace(TraceUtils.getTraceFromTraceur(TraceCalculImpactEquipementPhysiqueUtils.buildTraceErreur(exception))) .build(); } @@ -167,7 +165,7 @@ public class CalculImpactEquipementPhysiqueServiceImpl implements CalculImpactEq if (demandeCalcul.getEquipementPhysique().getConsoElecAnnuelle() != null) { var valeur = demandeCalcul.getEquipementPhysique().getConsoElecAnnuelle(); return ConsoElecAnMoyenne.builder() - .valeurEquipementConsoElecAnnuelle(valeur) + .valeurItemConsoElecAnnuelle(valeur) .valeur(valeur) .build(); } @@ -192,7 +190,7 @@ public class CalculImpactEquipementPhysiqueServiceImpl implements CalculImpactEq var valeur = referentielImpactEquipementOpt.get().getConsoElecMoyenne(); return ConsoElecAnMoyenne.builder() - .sourceReferentielImpactEquipement(referentielImpactEquipementOpt.get().getSource()) + .sourceReferentielFacteurCaracterisation(referentielImpactEquipementOpt.get().getSource()) .valeurReferentielConsoElecMoyenne(valeur) .valeur(valeur) .build(); @@ -301,3 +299,4 @@ public class CalculImpactEquipementPhysiqueServiceImpl implements CalculImpactEq } } } + diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactEquipementVirtuelServiceImpl.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactEquipementVirtuelServiceImpl.java index ef137c98ed35cecf4b70a9bd130065e6026c36b2..06915a5d95828483f6611dd77320e8d251b52af0 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactEquipementVirtuelServiceImpl.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactEquipementVirtuelServiceImpl.java @@ -1,6 +1,5 @@ package org.mte.numecoeval.calculs.domain.port.input.service.impl; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactEquipementVirtuel; @@ -19,7 +18,6 @@ public class CalculImpactEquipementVirtuelServiceImpl implements CalculImpactEqu private static final String VERSION_CALCUL = "1.1"; public static final String TYPE_EQUIPEMENT_VIRTUEL_STOCKAGE = "stockage"; public static final String TYPE_EQUIPEMENT_VIRTUEL_CALCUL = "calcul"; - private final ObjectMapper objectMapper; @Override public ImpactEquipementVirtuel calculerImpactEquipementVirtuel(DemandeCalculImpactEquipementVirtuel demandeCalcul) { @@ -76,7 +74,7 @@ public class CalculImpactEquipementVirtuelServiceImpl implements CalculImpactEqu .critere(demandeCalcul.getImpactEquipement().getCritere()) .unite(demandeCalcul.getImpactEquipement().getUnite()) .statutIndicateur("OK") - .trace(TraceUtils.getTraceFromTraceur(objectMapper, trace)) + .trace(TraceUtils.getTraceFromTraceur(trace)) .nomLot(demandeCalcul.getEquipementVirtuel().getNomLot()) .nomSourceDonnee(demandeCalcul.getEquipementVirtuel().getNomSourceDonnee()) .dateLot(demandeCalcul.getEquipementVirtuel().getDateLot()) @@ -88,6 +86,7 @@ public class CalculImpactEquipementVirtuelServiceImpl implements CalculImpactEqu .impactUnitaire(result.valeurImpactUnitaire()) .consoElecMoyenne(result.consoElecMoyenne()) .idEntree(demandeCalcul.getEquipementVirtuel().getId()) + .qualite(demandeCalcul.getEquipementVirtuel().getQualite()) .build(); } @@ -99,7 +98,7 @@ public class CalculImpactEquipementVirtuelServiceImpl implements CalculImpactEqu .critere(demandeCalcul.getImpactEquipement().getCritere()) .unite(demandeCalcul.getImpactEquipement().getUnite()) .statutIndicateur("ERREUR") - .trace(TraceUtils.getTraceFromTraceur(objectMapper, TraceCalculImpactVirtuelUtils.buildTraceErreur(exception))) + .trace(TraceUtils.getTraceFromTraceur(TraceCalculImpactVirtuelUtils.buildTraceErreur(exception))) .nomLot(demandeCalcul.getEquipementVirtuel().getNomLot()) .nomSourceDonnee(demandeCalcul.getEquipementVirtuel().getNomSourceDonnee()) .dateLot(demandeCalcul.getEquipementVirtuel().getDateLot()) @@ -111,6 +110,7 @@ public class CalculImpactEquipementVirtuelServiceImpl implements CalculImpactEqu .impactUnitaire(null) .consoElecMoyenne(null) .idEntree(demandeCalcul.getEquipementVirtuel().getId()) + .qualite(demandeCalcul.getEquipementVirtuel().getQualite()) .build(); } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactMessagerieServiceImpl.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactMessagerieServiceImpl.java index 35fa91dac13a1198ce21ddfa4feba080f2fa5cdb..ac74311c1601f5c6461e10d880d17eadd842e71c 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactMessagerieServiceImpl.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactMessagerieServiceImpl.java @@ -1,6 +1,5 @@ package org.mte.numecoeval.calculs.domain.port.input.service.impl; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactMessagerie; @@ -16,7 +15,6 @@ import org.mte.numecoeval.calculs.domain.traceur.TraceUtils; @AllArgsConstructor public class CalculImpactMessagerieServiceImpl implements CalculImpactMessagerieService { private static final String VERSION_CALCUL = "1.0"; - private final ObjectMapper objectMapper; @Override public ImpactMessagerie calculerImpactMessagerie(DemandeCalculImpactMessagerie demandeCalcul) { @@ -79,7 +77,7 @@ public class CalculImpactMessagerieServiceImpl implements CalculImpactMessagerie .nomEntite(demandeCalcul.getMessagerie().getNomEntite()) .nomOrganisation(demandeCalcul.getMessagerie().getNomOrganisation()) .versionCalcul(VERSION_CALCUL) - .trace(TraceUtils.getTraceFromTraceur(objectMapper, TraceCalculImpactMessagerieUtils.buildTrace(demandeCalcul, referentielImpactMessagerie))) + .trace(TraceUtils.getTraceFromTraceur(TraceCalculImpactMessagerieUtils.buildTrace(demandeCalcul, referentielImpactMessagerie))) .build(); } @@ -99,7 +97,7 @@ public class CalculImpactMessagerieServiceImpl implements CalculImpactMessagerie .nomEntite(demandeCalcul.getMessagerie().getNomEntite()) .nomOrganisation(demandeCalcul.getMessagerie().getNomOrganisation()) .versionCalcul(VERSION_CALCUL) - .trace(TraceUtils.getTraceFromTraceur(objectMapper, TraceCalculImpactMessagerieUtils.buildTraceError(exception))) + .trace(TraceUtils.getTraceFromTraceur(TraceCalculImpactMessagerieUtils.buildTraceError(exception))) .build(); } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactOperationNonITServiceImpl.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactOperationNonITServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..8390463ed6dff00641f10cb1221469fd4217e942 --- /dev/null +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactOperationNonITServiceImpl.java @@ -0,0 +1,372 @@ +package org.mte.numecoeval.calculs.domain.port.input.service.impl; + +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactOperationNonIT; +import org.mte.numecoeval.calculs.domain.data.demande.MetadataCalcul; +import org.mte.numecoeval.calculs.domain.data.erreur.TypeErreurCalcul; +import org.mte.numecoeval.calculs.domain.data.indicateurs.ImpactOperationNonIT; +import org.mte.numecoeval.calculs.domain.data.referentiel.ReferentielFacteurCaracterisation; +import org.mte.numecoeval.calculs.domain.data.referentiel.ReferentielHypothese; +import org.mte.numecoeval.calculs.domain.data.trace.*; +import org.mte.numecoeval.calculs.domain.exception.CalculImpactException; +import org.mte.numecoeval.calculs.domain.port.input.service.CalculImpactOperationNonITService; +import org.mte.numecoeval.calculs.domain.traceur.TraceCalculImpactOperationNonITUtils; +import org.mte.numecoeval.calculs.domain.traceur.TraceUtils; + +import java.util.Optional; + +import static org.mte.numecoeval.calculs.domain.traceur.TraceCalculImpactOperationNonITUtils.*; +import static org.mte.numecoeval.calculs.domain.utils.Constants.*; + +@Slf4j +@AllArgsConstructor +public class CalculImpactOperationNonITServiceImpl implements CalculImpactOperationNonITService { + private static final String VERSION_CALCUL = "1.0"; + + public ImpactOperationNonIT calculerImpactOperationNonIT(DemandeCalculImpactOperationNonIT demandeCalcul) { + log.debug("Début de calcul d'impact d'un item non it : {}, {}, {} ", + demandeCalcul.getEtape().getCode(), + demandeCalcul.getCritere().getNomCritere(), + demandeCalcul.getOperationNonIT().getNomItemNonIT()); + ImpactOperationNonIT impactErreur = null; + + try { + return getCalculImpactOperationNonIT(demandeCalcul); + } catch (CalculImpactException e) { + log.debug("Erreur de calcul impact item: Type: {}, Cause: {}, Etape: {}, Critere: {}, Item Physique: {}, RefItemRetenu: {}, RefItemParDefaut: {}", + e.getErrorType(), + e.getMessage(), + demandeCalcul.getEtape().getCode(), + demandeCalcul.getCritere().getNomCritere(), + demandeCalcul.getOperationNonIT().getNomItemNonIT(), + demandeCalcul.getTypeItem().getType(), + demandeCalcul.getRefItemParDefaut()); + impactErreur = buildCalculImpactForError(demandeCalcul, e); + } catch (Exception e) { + log.debug("{} : Erreur de calcul impact item physique: Erreur technique de l'indicateur : {}", TypeErreurCalcul.ERREUR_TECHNIQUE.getCode(), e.getMessage()); + impactErreur = buildCalculImpactForError(demandeCalcul, new CalculImpactException(TypeErreurCalcul.ERREUR_TECHNIQUE.getCode(), "Erreur publication de l'indicateur : " + e.getMessage())); + } + return impactErreur; + } + + private ImpactOperationNonIT getCalculImpactOperationNonIT(DemandeCalculImpactOperationNonIT demandeCalcul) throws CalculImpactException { + MetadataCalcul metadataCalcul = switch (demandeCalcul.getTypeItem().getCategorie()) { + case CATEGORIE_RESEAU_MOBILE, CATEGORIE_MAINTENANCE -> getFormule(demandeCalcul); + case CATEGORIE_RESEAU_FIXE -> getFormuleReseauFixe(demandeCalcul); + case CATEGORIE_BATIMENT -> getFormuleBatiment(demandeCalcul); + case CATEGORIE_DEPLACEMENT_ELECTRIQUE -> getFormuleUtilisationDeplacementVehiculeElectrique(demandeCalcul); + case CATEGORIE_DEPLACEMENT_ESSENCE -> getFormuleUtilisationDeplacementVehiculeEssence(demandeCalcul); + case CATEGORIE_DEPLACEMENT_HYBRIDE -> getFormuleUtilisationDeplacementVehiculeHybride(demandeCalcul); + default -> + throw new CalculImpactException(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), "La catégorie renseignée est invalide"); + }; + if (metadataCalcul == null) { + return null; + } + var calcul = buildCalculImpactOperationNonIT(demandeCalcul, metadataCalcul.valeurImpactUnitaire(), metadataCalcul.traceCalculImpactOperationNonIT()); + calcul.setTrace(TraceUtils.getTraceFromTraceur(metadataCalcul.traceCalculImpactOperationNonIT())); + return calcul; + } + + private MetadataCalcul getFormule(DemandeCalculImpactOperationNonIT demandeCalcul) throws CalculImpactException { + if ("UTILISATION".equals(demandeCalcul.getEtape().getCode())) { + return getFormuleUtilisationDefaut(demandeCalcul); + } else { + return getFormuleDefaut(demandeCalcul); + } + } + + private MetadataCalcul getFormuleDefaut(DemandeCalculImpactOperationNonIT demandeCalcul) throws CalculImpactException { + // si l'étape n'est pas UTILISATION, base de la formule commune à toutes les catégories + Double quantite = demandeCalcul.getOperationNonIT().getQuantite(); + ReferentielFacteurCaracterisation referentielFacteurCaracterisation = getImpactItem(demandeCalcul); + Double valeurReferentiel = referentielFacteurCaracterisation.getValeur(); + Double valeurImpactUnitaire = quantite * valeurReferentiel; + TraceCalculImpactOperationNonIT traceCalculImpactOperationNonIT = TraceCalculImpactOperationNonITUtils.buildTrace(null, null, referentielFacteurCaracterisation.getValeur(), referentielFacteurCaracterisation.getSource(), null, null, null); + traceCalculImpactOperationNonIT.setFormule(getFormuleBase(quantite, valeurReferentiel)); + return new MetadataCalcul(valeurImpactUnitaire, traceCalculImpactOperationNonIT); + } + + private MetadataCalcul getFormuleUtilisationDefaut(DemandeCalculImpactOperationNonIT demandeCalcul) throws CalculImpactException { + // base de la formule commune à toutes les catégories de formule + Double quantite = demandeCalcul.getOperationNonIT().getQuantite(); + ConsoElecAnMoyenne consoElecMoyenne = getConsoElecAnMoyenne(demandeCalcul); + MixElectrique mixelec = getMixElectrique(demandeCalcul); + Double valeurImpactUnitaire = quantite * consoElecMoyenne.getValeur() * mixelec.getValeur(); + TraceCalculImpactOperationNonIT traceCalculImpactOperationNonIT = TraceCalculImpactOperationNonITUtils.buildTrace(consoElecMoyenne, mixelec, null, null, null, null, null); + traceCalculImpactOperationNonIT.setFormule(getFormuleUtilisation(quantite, consoElecMoyenne.getValeur(), mixelec.getValeur())); + traceCalculImpactOperationNonIT.setConsoElecAnMoyenne(consoElecMoyenne); + return new MetadataCalcul(valeurImpactUnitaire, traceCalculImpactOperationNonIT); + } + + private MetadataCalcul getFormuleReseauFixe(DemandeCalculImpactOperationNonIT demandeCalcul) throws CalculImpactException { + MetadataCalcul metadataCalcul = getFormule(demandeCalcul); + Hypothese hypothese = getHypothese(demandeCalcul); + Double fixedLineCapacity = hypothese.getValeur(); + Double valeurImpactUnitaire = metadataCalcul.valeurImpactUnitaire() / fixedLineCapacity; + TraceCalculImpactOperationNonIT traceCalculImpactOperationNonIT = metadataCalcul.traceCalculImpactOperationNonIT(); + String traceFormuleBase = traceCalculImpactOperationNonIT.getFormule(); + traceCalculImpactOperationNonIT.setFormule(traceFormuleBase + " / CapaciteLigneFixe(%s)".formatted(fixedLineCapacity)); + traceCalculImpactOperationNonIT.setHypothese(hypothese); + return new MetadataCalcul(valeurImpactUnitaire, traceCalculImpactOperationNonIT); + } + + private MetadataCalcul getFormuleBatiment(DemandeCalculImpactOperationNonIT demandeCalcul) throws CalculImpactException { + if ("UTILISATION".equals(demandeCalcul.getEtape().getCode())) { + return null; + } + MetadataCalcul metadataCalcul = getFormule(demandeCalcul); + DureeDeVie dureeDeVie = getDureeVie(demandeCalcul); + Double dureeDeVieValeur = dureeDeVie.getValeurRetenue(); + Double valeurImpactUnitaire = metadataCalcul.valeurImpactUnitaire() / dureeDeVieValeur; + TraceCalculImpactOperationNonIT traceCalculImpactOperationNonIT = metadataCalcul.traceCalculImpactOperationNonIT(); + String traceFormuleBase = traceCalculImpactOperationNonIT.getFormule(); + traceCalculImpactOperationNonIT.setFormule(traceFormuleBase + " / DureeDeVie(%s)".formatted(dureeDeVieValeur)); + traceCalculImpactOperationNonIT.setDureeDeVie(dureeDeVie); + return new MetadataCalcul(valeurImpactUnitaire, traceCalculImpactOperationNonIT); + } + + private MetadataCalcul getFormuleUtilisationDeplacementVehiculeEssence(DemandeCalculImpactOperationNonIT demandeCalcul) throws CalculImpactException { + if (!"UTILISATION".equals(demandeCalcul.getEtape().getCode())) { + return null; + } + Double quantite = demandeCalcul.getOperationNonIT().getQuantite(); + Hypothese hypothese = getHypothese(demandeCalcul); + Double consoMoyenne = hypothese.getValeur(); + ReferentielFacteurCaracterisation referentielFacteurCaracterisation = getImpactItem(demandeCalcul); + Double valeurReferentiel = referentielFacteurCaracterisation.getValeur(); + Double valeurImpactUnitaire = consoMoyenne * quantite * valeurReferentiel; + TraceCalculImpactOperationNonIT traceCalculImpactOperationNonIT = TraceCalculImpactOperationNonITUtils.buildTrace(null, null, referentielFacteurCaracterisation.getValeur(), referentielFacteurCaracterisation.getSource(), hypothese, null, null); + traceCalculImpactOperationNonIT.setFormule(getFormuleDeplacement(consoMoyenne, quantite) + " * ReferentielFacteurCaracterisation(%s))".formatted(valeurReferentiel)); + return new MetadataCalcul(valeurImpactUnitaire, traceCalculImpactOperationNonIT); + + } + + private MetadataCalcul getFormuleUtilisationDeplacementVehiculeHybride(DemandeCalculImpactOperationNonIT demandeCalcul) throws CalculImpactException { + if (!"UTILISATION".equals(demandeCalcul.getEtape().getCode())) { + return null; + } + Double quantite = demandeCalcul.getOperationNonIT().getQuantite(); + Hypothese hypothese = getHypothese(demandeCalcul); + Double consoMoyenne = hypothese.getValeur(); + ReferentielFacteurCaracterisation referentielFacteurCaracterisation = getImpactItem(demandeCalcul); + Double valeurReferentiel = referentielFacteurCaracterisation.getValeur(); + Double valeurImpactUnitaire = consoMoyenne * quantite * valeurReferentiel; + TraceCalculImpactOperationNonIT traceCalculImpactOperationNonIT = TraceCalculImpactOperationNonITUtils.buildTrace(null, null, referentielFacteurCaracterisation.getValeur(), referentielFacteurCaracterisation.getSource(), hypothese, null, null); + Hypothese hypotheseTauxHybride = getTauxHybride(demandeCalcul); + valeurImpactUnitaire = valeurImpactUnitaire * hypotheseTauxHybride.getValeur(); + traceCalculImpactOperationNonIT.setFormule(getFormuleDeplacement(consoMoyenne, quantite) + " * ReferentielFacteurCaracterisation(%s) * TauxHybride(%s))".formatted(valeurReferentiel, hypotheseTauxHybride.getValeur())); + return new MetadataCalcul(valeurImpactUnitaire, traceCalculImpactOperationNonIT); + } + + private MetadataCalcul getFormuleUtilisationDeplacementVehiculeElectrique(DemandeCalculImpactOperationNonIT demandeCalcul) throws CalculImpactException { + if (!"UTILISATION".equals(demandeCalcul.getEtape().getCode())) { + return null; + } + Double quantite = demandeCalcul.getOperationNonIT().getQuantite(); + Hypothese hypothese = getHypothese(demandeCalcul); + Double consoMoyenne = hypothese.getValeur(); + MixElectrique mixelec = getMixElectrique(demandeCalcul); + Double valeurImpactUnitaire = consoMoyenne * quantite * mixelec.getValeur(); + TraceCalculImpactOperationNonIT traceCalculImpactOperationNonIT = TraceCalculImpactOperationNonITUtils.buildTrace(null, mixelec, null, null, null, null, null); + traceCalculImpactOperationNonIT.setFormule(getFormuleDeplacement(consoMoyenne, quantite) + " * MixElectrique(%s))".formatted(mixelec.getValeur())); + return new MetadataCalcul(valeurImpactUnitaire, traceCalculImpactOperationNonIT); + } + + private ImpactOperationNonIT buildCalculImpactOperationNonIT(DemandeCalculImpactOperationNonIT demandeCalcul, Double valeurImpactUnitaire, TraceCalculImpactOperationNonIT traceCalculImpactOperationNonIT) { + ImpactOperationNonIT result = ImpactOperationNonIT + .builder() + .nomItemNonIT(demandeCalcul.getOperationNonIT().getNomItemNonIT()) + .etapeACV(demandeCalcul.getEtape().getCode()) + .critere(demandeCalcul.getCritere().getNomCritere()) + .dateCalcul(demandeCalcul.getDateCalcul()) + .versionCalcul(VERSION_CALCUL) + .typeItem(demandeCalcul.getOperationNonIT().getType()) + .quantite(demandeCalcul.getOperationNonIT().getQuantite()) + .statutIndicateur("OK") + .impactUnitaire(valeurImpactUnitaire) + .unite(demandeCalcul.getCritere().getUnite()) + .nomLot(demandeCalcul.getOperationNonIT().getNomLot()) + .nomSourceDonnee(demandeCalcul.getOperationNonIT().getNomSourceDonnee()) + .dateLot(demandeCalcul.getOperationNonIT().getDateLot()) + .nomEntite(demandeCalcul.getOperationNonIT().getNomEntite()) + .nomOrganisation(demandeCalcul.getOperationNonIT().getNomOrganisation()) + .qualite(demandeCalcul.getOperationNonIT().getQualite()) + .build(); + if (traceCalculImpactOperationNonIT.getConsoElecAnMoyenne() != null) { + result.setConsoElecMoyenne(traceCalculImpactOperationNonIT.getConsoElecAnMoyenne().getValeur()); + } + return result; + } + + private ImpactOperationNonIT buildCalculImpactForError(DemandeCalculImpactOperationNonIT demandeCalcul, CalculImpactException exception) { + + return ImpactOperationNonIT + .builder() + .nomItemNonIT(demandeCalcul.getOperationNonIT().getNomItemNonIT()) + .etapeACV(demandeCalcul.getEtape().getCode()) + .critere(demandeCalcul.getCritere().getNomCritere()) + .dateCalcul(demandeCalcul.getDateCalcul()) + .versionCalcul(VERSION_CALCUL) + .typeItem(demandeCalcul.getOperationNonIT().getType()) + .quantite(demandeCalcul.getOperationNonIT().getQuantite()) + .statutIndicateur("ERREUR") + .impactUnitaire(null) + .unite(demandeCalcul.getCritere().getUnite()) + .consoElecMoyenne(null) + .nomLot(demandeCalcul.getOperationNonIT().getNomLot()) + .nomSourceDonnee(demandeCalcul.getOperationNonIT().getNomSourceDonnee()) + .dateLot(demandeCalcul.getOperationNonIT().getDateLot()) + .nomEntite(demandeCalcul.getOperationNonIT().getNomEntite()) + .nomOrganisation(demandeCalcul.getOperationNonIT().getNomOrganisation()) + .trace(TraceUtils.getTraceFromTraceur(TraceCalculImpactOperationNonITUtils.buildTraceErreur(exception))) + .qualite(demandeCalcul.getOperationNonIT().getQualite()) + .build(); + } + + private Hypothese getHypothese(DemandeCalculImpactOperationNonIT demandeCalcul) throws CalculImpactException { + Optional<ReferentielHypothese> hypothese = demandeCalcul.getHypotheseFromCode(demandeCalcul.getTypeItem().getRefHypothese()); + if (hypothese.isPresent() && hypothese.get().getValeur() != null) { + return Hypothese.builder() + .valeur(hypothese.get().getValeur()) + .nom_hypothese(hypothese.get().getCode()) + .source(hypothese.get().getSource()) + .build(); + } + throw new CalculImpactException( + TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), + "Il n'y a pas d'hypothese pour l'item pour la refHypothese '" + demandeCalcul.getTypeItem().getRefHypothese() + "' de l'item " + demandeCalcul.getOperationNonIT().getNomItemNonIT()); + + } + + private Hypothese getTauxHybride(DemandeCalculImpactOperationNonIT demandeCalcul) throws CalculImpactException { + var hypothese = demandeCalcul.getHypotheseFromCode("TAUX_VEHICULE_HYBRIDE"); + if (hypothese.isPresent() && hypothese.get().getValeur() != null) { + return Hypothese.builder() + .valeur(hypothese.get().getValeur()) + .nom_hypothese(hypothese.get().getCode()) + .source(hypothese.get().getSource()) + .build(); + } + throw new CalculImpactException(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), "Il n'y a pas de taux renseigné pour les véhicules hybrides dans la table des références"); + } + + private ReferentielFacteurCaracterisation getImpactItem(DemandeCalculImpactOperationNonIT demandeCalcul) throws CalculImpactException { + Optional<ReferentielFacteurCaracterisation> facteurCaracterisation = demandeCalcul.getFacteurCaracterisation(demandeCalcul.getTypeItem().getRefItemParDefaut()); + if (facteurCaracterisation.isPresent() && facteurCaracterisation.get().getValeur() != null) { + return facteurCaracterisation.get(); + } else { + throw new CalculImpactException(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), "Référentiel Facteur Caractérisation inconnu"); + } + } + + private ConsoElecAnMoyenne getConsoElecAnMoyenne(DemandeCalculImpactOperationNonIT demandeCalcul) throws CalculImpactException { + if (demandeCalcul.getOperationNonIT().getConsoElecAnnuelle() != null) { + var valeur = demandeCalcul.getOperationNonIT().getConsoElecAnnuelle(); + return ConsoElecAnMoyenne.builder() + .valeurItemConsoElecAnnuelle(valeur) + .valeur(valeur) + .build(); + } + if (StringUtils.isBlank(demandeCalcul.getRefItemParDefaut())) { + throw new CalculImpactException(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), "Référentiel Facteur Caractérisation inconnu"); + } + + var referentielFacteurCaracterisation = getImpactItem(demandeCalcul); + if (referentielFacteurCaracterisation.getConsoElecMoyenne() == null) { + throw new CalculImpactException(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), + "Donnée de consommation electrique manquante : operationNonIT : " + demandeCalcul.getOperationNonIT().getNomItemNonIT() + + ", RefItemParDefaut : " + demandeCalcul.getTypeItem().getRefItemParDefaut() + + ); + } + + var valeur = referentielFacteurCaracterisation.getConsoElecMoyenne(); + return ConsoElecAnMoyenne.builder() + .sourceReferentielFacteurCaracterisation(referentielFacteurCaracterisation.getSource()) + .valeurReferentielConsoElecMoyenne(valeur) + .valeur(valeur) + .build(); + + } + + private MixElectrique getMixElectrique(DemandeCalculImpactOperationNonIT demandeCalcul) throws CalculImpactException { + if (StringUtils.isNotBlank(demandeCalcul.getOperationNonIT().getLocalisation())) { + Optional<ReferentielFacteurCaracterisation> refMixElecOpt = demandeCalcul.getMixElectriqueFromFacteurCaracterisation(demandeCalcul.getOperationNonIT().getLocalisation()); + if (refMixElecOpt.isPresent()) { + var refMixElec = refMixElecOpt.get(); + return MixElectrique.builder() + .valeur(refMixElec.getValeur()) + .valeurReferentielMixElectrique(refMixElec.getValeur()) + .sourceReferentielMixElectrique(refMixElec.getSource()) + .build(); + } + } + throw new CalculImpactException(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), + "Il n'existe pas de Mix électrique pour cet item non it : critere: " + demandeCalcul.getCritere().getNomCritere() + + " - operation non it: " + demandeCalcul.getOperationNonIT().getNomItemNonIT() + + " - Localisation: " + demandeCalcul.getOperationNonIT().getLocalisation() + ); + + } + + /** + * Si la duree de vie est renseignée dans l'opérationNonIT, on retourne cette valeur + * Sinon, si la valeur est renseignée dans la table ref_typeitem correspondant à cet item, on retourne cette valeur + * Sinon, si dans la table ref_hypothèse on a une valeur pour la clé "dureeVieDatacenter", on utilise cette valeur + * Sinon, on renvoie une erreur + * + * @param demandeCalcul la demande de calcul + * @return dureeDeVie + * @throws CalculImpactException sinon + */ + public DureeDeVie getDureeVie(DemandeCalculImpactOperationNonIT demandeCalcul) throws CalculImpactException { + + var dureeDeVie = DureeDeVie.builder().build(); + + Double dureeInventaire = demandeCalcul.getOperationNonIT().getDureeDeVie(); + if (dureeInventaire != null) { + dureeDeVie.setValeurRetenue(dureeInventaire < 1 ? 1.0 : dureeInventaire); + return dureeDeVie; + } + + // dureeInventaire est null + // recuperation duree de vie via typeItem + if (demandeCalcul.getTypeItem() != null) { + var dureeVieDefaut = demandeCalcul.getTypeItem().getDureeVieDefaut(); + + if (dureeVieDefaut != null) { + Double duree = dureeVieDefaut < 1 ? 1 : dureeVieDefaut; + dureeDeVie.setDureeDeVieParDefaut(DureeDeVieParDefaut.builder() + .valeurTypeItemDureeVieDefaut(duree) + .valeur(duree) + .sourceTypeItemDureeVieDefaut(demandeCalcul.getTypeItem().getSource()) + .build()); + + dureeDeVie.setValeurRetenue(duree); + return dureeDeVie; + } + } + + // dureeInventaire est null + // typeItem est null + // recuperation duree de vie via hypothese 'dureeVieBatimentParDefaut' + var hypothese = demandeCalcul.getHypotheseFromCode("dureeVieBatimentParDefaut") + .orElseThrow(() -> new CalculImpactException(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), "La durée de vie par défaut de l'item n'a pas pu être déterminée")); + + if (hypothese.getValeur() != null) { + Double duree = hypothese.getValeur() < 1 ? 1 : hypothese.getValeur(); + dureeDeVie.setDureeDeVieParDefaut(DureeDeVieParDefaut.builder() + .valeurReferentielHypothese(duree) + .sourceReferentielHypothese(hypothese.getSource()) + .valeur(duree) + .build()); + + dureeDeVie.setValeurRetenue(duree); + } + + return dureeDeVie; + } +} diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactReseauServiceImpl.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactReseauServiceImpl.java index d9fe16ac9451b6a4778464733aa0624de5932d33..74f449d0d5325d86b4ff41b78e17e9c89b4e4c16 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactReseauServiceImpl.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/CalculImpactReseauServiceImpl.java @@ -1,6 +1,5 @@ package org.mte.numecoeval.calculs.domain.port.input.service.impl; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactReseau; @@ -20,8 +19,6 @@ public class CalculImpactReseauServiceImpl implements CalculImpactReseauService private static final String VERSION_CALCUL = "1.0"; - private final ObjectMapper objectMapper; - @Override public ImpactReseau calculerImpactReseau(DemandeCalculImpactReseau demandeCalcul) { try { @@ -106,7 +103,6 @@ public class CalculImpactReseauServiceImpl implements CalculImpactReseauService .unite(referentielImpactReseau.getUnite()) .trace( TraceUtils.getTraceFromTraceur( - objectMapper, TraceCalculImpactReseauUtils.buildTrace(demandeCalcul, referentielImpactReseau)) ) .build(); @@ -129,7 +125,6 @@ public class CalculImpactReseauServiceImpl implements CalculImpactReseauService .impactUnitaire(null) .unite(demandeCalcul.getCritere().getUnite()) .trace(TraceUtils.getTraceFromTraceur( - objectMapper, TraceCalculImpactReseauUtils.buildTraceErreur(exception)) ) .build(); diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/DureeDeVieEquipementPhysiqueServiceImpl.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/DureeDeVieEquipementPhysiqueServiceImpl.java index 717db5f02be59ada9e1a833dbb02339a95a34e1f..58e22f1d5c6f3f35de8e51456331ddb27debeb86 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/DureeDeVieEquipementPhysiqueServiceImpl.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/port/input/service/impl/DureeDeVieEquipementPhysiqueServiceImpl.java @@ -1,6 +1,7 @@ package org.mte.numecoeval.calculs.domain.port.input.service.impl; import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactEquipementPhysique; import org.mte.numecoeval.calculs.domain.data.erreur.TypeErreurCalcul; import org.mte.numecoeval.calculs.domain.data.referentiel.ReferentielHypothese; @@ -13,57 +14,127 @@ import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; +@Slf4j @AllArgsConstructor public class DureeDeVieEquipementPhysiqueServiceImpl implements DureeDeVieEquipementPhysiqueService { @Override public DureeDeVie calculerDureeVie(DemandeCalculImpactEquipementPhysique demandeCalcul) throws CalculImpactException { + String methodeDureeUsage = demandeCalcul.getOptionsCalcul() != null ? demandeCalcul.getOptionsCalcul().dureeUsage() : "FIXE"; + + if ("REEL".equals(methodeDureeUsage)) { + return calculDureeUsageFromMethodeReel(demandeCalcul); + } + // par défaut, methodeDureeUsage == "FIXE" + return calculDureeUsageFromMethodeFixe(demandeCalcul); + } + + private DureeDeVie calculDureeUsageAmontEtAval(DemandeCalculImpactEquipementPhysique demandeCalcul) throws CalculImpactException { + var result = DureeDeVie.builder() + .valeurRetenue(0.0) + .build(); + + Double dureeUsageAmont = demandeCalcul.getEquipementPhysique().getDureeUsageAmont(); + if (dureeUsageAmont != null) { + if (dureeUsageAmont < 0) { + throw new CalculImpactException(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), "La durée d'usage amont ne peut pas être négative"); + } + result.setDureeUsageAmont(dureeUsageAmont); + result.setValeurRetenue(dureeUsageAmont); + } else { + result.setDureeUsageAmont(0.0); + } + + Double dureeUsageAval = demandeCalcul.getEquipementPhysique().getDureeUsageAval(); + if (dureeUsageAval != null) { + if (dureeUsageAval < 0) { + throw new CalculImpactException(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), "La durée d'usage aval ne peut pas être négative"); + } + result.setDureeUsageAval(dureeUsageAval); + result.setValeurRetenue(result.getValeurRetenue() + dureeUsageAval); + } else { + result.setDureeUsageAval(0.0); + } + return result; + } + + private DureeDeVie calculDureeUsageFromMethodeReel(DemandeCalculImpactEquipementPhysique demandeCalcul) throws CalculImpactException { + DureeDeVie result = calculDureeUsageAmontEtAval(demandeCalcul); + result.setMethodeDureeUsage("REEL"); var dateAchat = demandeCalcul.getEquipementPhysique().getDateAchat(); var dateRetrait = demandeCalcul.getEquipementPhysique().getDateRetrait(); - var result = DureeDeVie.builder().build(); - if (dateAchat != null && dateRetrait != null) { - - if (dateAchat.isBefore(dateRetrait)) { - Double valeur ; - if (ChronoUnit.MONTHS.between(dateAchat, dateRetrait) < 12) { - valeur= 1d; - } else { - valeur = ChronoUnit.DAYS.between(dateAchat, dateRetrait) / 365d; - } - result.setValeur(valeur); - result.setDateAchat(dateAchat.format(DateTimeFormatter.ISO_DATE)); - result.setDateRetrait(dateRetrait.format(DateTimeFormatter.ISO_DATE)); + + if (dateAchat != null) { + // Si la date d'achat est présente et non la date de retrait, la date du jour devient la date de retrait pour le calcul + var dateRetraitReelle = dateRetrait == null ? LocalDate.now() : dateRetrait; + if (!dateAchat.isBefore(dateRetraitReelle)) { + throw new CalculImpactException(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), "La durée de vie de l'équipement n'a pas pu être déterminée"); + } + + var dureeAnneeUtilisation = ChronoUnit.DAYS.between(dateAchat, dateRetraitReelle) / 365d; + + if (dureeAnneeUtilisation + result.getDureeUsageAmont() + result.getDureeUsageAval() < 1) { + result.setValeurRetenue(1.0); } else { - throw new CalculImpactException(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(),"La durée de vie de l'équipement n'a pas pu être déterminée"); + result.setValeurRetenue(result.getValeurRetenue() + dureeAnneeUtilisation); } - } - // Taiga#864 - Si la date d'achat est présente et non la date de retrait, on prend la date du jour devient la date de retrait pour le calcul - else if (dateAchat != null) { - result.setValeur( - ChronoUnit.DAYS.between(dateAchat, LocalDate.now()) / 365d - ); + result.setDateAchat(dateAchat.format(DateTimeFormatter.ISO_DATE)); - result.setDateRetrait(LocalDate.now().format(DateTimeFormatter.ISO_DATE)); + result.setDateRetrait(dateRetraitReelle.format(DateTimeFormatter.ISO_DATE)); + return result; + } + + // dateAchat et dateRetrait sont null + var dureeDeVieParDefaut = calculerDureeVieDefaut(demandeCalcul); + result.setDureeDeVieParDefaut(dureeDeVieParDefaut); + if (dureeDeVieParDefaut.getValeur() + result.getDureeUsageAmont() + result.getDureeUsageAval() < 1) { + result.setValeurRetenue(1.0); + } + result.setValeurRetenue(result.getValeurRetenue() + dureeDeVieParDefaut.getValeur()); + return result; + } + + private DureeDeVie calculDureeUsageFromMethodeFixe(DemandeCalculImpactEquipementPhysique demandeCalcul) throws CalculImpactException { + DureeDeVie result = calculDureeUsageAmontEtAval(demandeCalcul); + result.setMethodeDureeUsage("FIXE"); + Double dureeUsageInterne = demandeCalcul.getEquipementPhysique().getDureeUsageInterne(); + if (dureeUsageInterne != null) { + if (dureeUsageInterne <= 0.0) { + throw new CalculImpactException(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), "La durée d'usage interne ne peut pas être négative ou nulle"); + } + result.setDureeUsageInterne(dureeUsageInterne); + if (dureeUsageInterne + result.getDureeUsageAmont() + result.getDureeUsageAval() < 1) { + result.setValeurRetenue(1.0); + } else { + result.setValeurRetenue(result.getValeurRetenue() + dureeUsageInterne); + } + return result; } - else { - var dureeDeVieParDefaut = calculerDureeVieDefaut(demandeCalcul); - result.setDureeDeVieParDefaut(dureeDeVieParDefaut); - result.setValeur(dureeDeVieParDefaut.getValeur()); + + // dureeUsageInterne est null + var dureeDeVieParDefaut = calculerDureeVieDefaut(demandeCalcul); + result.setDureeDeVieParDefaut(dureeDeVieParDefaut); + if (dureeDeVieParDefaut.getValeur() + result.getDureeUsageAmont() + result.getDureeUsageAval() < 1) { + result.setValeurRetenue(1.0); + } else { + result.setValeurRetenue(result.getValeurRetenue() + dureeDeVieParDefaut.getValeur()); } - return result; + return result; } @Override public DureeDeVieParDefaut calculerDureeVieDefaut(DemandeCalculImpactEquipementPhysique demandeCalcul) throws CalculImpactException { - if(demandeCalcul.getTypeEquipement() != null && demandeCalcul.getTypeEquipement().getDureeVieDefaut() !=null){ + if (demandeCalcul.getTypeEquipement() != null && demandeCalcul.getTypeEquipement().getDureeVieDefaut() != null) { return DureeDeVieParDefaut.builder() - .valeurEquipementDureeVieDefaut(demandeCalcul.getTypeEquipement().getDureeVieDefaut()) + .valeurTypeItemDureeVieDefaut(demandeCalcul.getTypeEquipement().getDureeVieDefaut()) + .sourceTypeItemDureeVieDefaut(demandeCalcul.getTypeEquipement().getSource()) .valeur(demandeCalcul.getTypeEquipement().getDureeVieDefaut()) .build(); } - var refHypotheseOpt= demandeCalcul.getHypotheseFromCode("dureeVieParDefaut"); - if (refHypotheseOpt.isPresent() && refHypotheseOpt.get().getValeur() != null){ + + var refHypotheseOpt = demandeCalcul.getHypotheseFromCode("dureeVieParDefaut"); + if (refHypotheseOpt.isPresent() && refHypotheseOpt.get().getValeur() != null) { ReferentielHypothese hypothese = refHypotheseOpt.get(); return DureeDeVieParDefaut.builder() .valeurReferentielHypothese(hypothese.getValeur()) @@ -71,7 +142,6 @@ public class DureeDeVieEquipementPhysiqueServiceImpl implements DureeDeVieEquipe .valeur(hypothese.getValeur()) .build(); } - throw new CalculImpactException(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(),"La durée de vie par défaut de l'équipement n'a pas pu être déterminée"); + throw new CalculImpactException(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), "La durée de vie par défaut de l'équipement n'a pas pu être déterminée"); } - } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/traceur/TraceCalculImpactEquipementPhysiqueUtils.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/traceur/TraceCalculImpactEquipementPhysiqueUtils.java index d1aafb978376547ebca7a9c1ce70c12a64223142..42560d275d9e9d154b6a87c670de2c94975b6b51 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/traceur/TraceCalculImpactEquipementPhysiqueUtils.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/traceur/TraceCalculImpactEquipementPhysiqueUtils.java @@ -31,7 +31,7 @@ public class TraceCalculImpactEquipementPhysiqueUtils { public static TraceCalculImpactEquipementPhysique buildTraceSecondScenario(Double quantite, Double valeurRefrentiel, String sourceReferentiel, DureeDeVie dureeDeVie, Double taux_utilisation) { return TraceCalculImpactEquipementPhysique.builder() - .formule(getFormuleSecondScenario(quantite, valeurRefrentiel, dureeDeVie.getValeur(), taux_utilisation)) + .formule(getFormuleSecondScenario(quantite, valeurRefrentiel, dureeDeVie.getValeurRetenue(), taux_utilisation)) .valeurReferentielImpactEquipement(valeurRefrentiel) .sourceReferentielImpactEquipement(sourceReferentiel) .dureeDeVie(dureeDeVie) @@ -43,7 +43,7 @@ public class TraceCalculImpactEquipementPhysiqueUtils { } public static String getFormuleSecondScenario(Double quantite, Double valeurRefrentiel, Double dureeVie, Double taux_utilisation) { - return "ImpactEquipementPhysique = (Quantité(%s) * referentielImpactEquipement(%s) * TauxUtilisation(%s)) / dureeVie(%s)".formatted(quantite, valeurRefrentiel, taux_utilisation, dureeVie); + return "ImpactEquipementPhysique = (Quantité(%s) * referentielFacteurCaracterisation(%s) * TauxUtilisation(%s)) / dureeVie(%s)".formatted(quantite, valeurRefrentiel, taux_utilisation, dureeVie); } } diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/traceur/TraceCalculImpactOperationNonITUtils.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/traceur/TraceCalculImpactOperationNonITUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..8d25e9c67c64a000c1c1985905934511cba3ef90 --- /dev/null +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/traceur/TraceCalculImpactOperationNonITUtils.java @@ -0,0 +1,45 @@ +package org.mte.numecoeval.calculs.domain.traceur; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.mte.numecoeval.calculs.domain.data.trace.*; +import org.mte.numecoeval.calculs.domain.exception.CalculImpactException; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class TraceCalculImpactOperationNonITUtils { + public static TraceCalculImpactOperationNonIT buildTraceErreur(CalculImpactException exception) { + var message = "Erreur lors du calcul de l'impact de l'opération non IT"; + if (exception != null) { + message = exception.getErrorType() + " : " + exception.getMessage(); + } + return TraceCalculImpactOperationNonIT.builder() + .erreur(message) + .build(); + } + + public static TraceCalculImpactOperationNonIT buildTrace(ConsoElecAnMoyenne consoElecAnMoyenne, MixElectrique mixElectrique, Double valeurReferentielFacteurCaracterisation, String sourceReferentielFacteurCaracterisation, Hypothese hypothese, DureeDeVie dureeDeVie, String erreur) { + return TraceCalculImpactOperationNonIT.builder() + .consoElecAnMoyenne(consoElecAnMoyenne) + .mixElectrique(mixElectrique) + .valeurReferentielFacteurCaracterisation(valeurReferentielFacteurCaracterisation) + .sourceReferentielFacteurCaracterisation(sourceReferentielFacteurCaracterisation) + .hypothese(hypothese) + .dureeDeVie(dureeDeVie) + .erreur(erreur) + .build(); + } + + public static String getFormuleUtilisation(Double quantite, Double consoElecAnMoyenne, Double mixElectriqueValeur) { + return "ImpactOperationNonIT = (Quantité(%s) * ConsoElecAnMoyenne(%s) * MixElectrique(%s))".formatted(quantite, consoElecAnMoyenne, mixElectriqueValeur); + } + + public static String getFormuleBase(Double quantite, Double valeurReferentiel) { + return "ImpactOperationNonIT = (Quantité(%s) * ReferentielFacteurCaracterisation(%s))".formatted(quantite, valeurReferentiel); + } + + public static String getFormuleDeplacement(Double consoMoyenne, Double quantite) { + return "ImpactOperationNonIT = (ConsoMoyenne(%s) * NbKmParcourus(%s)".formatted(consoMoyenne, quantite); + } + + +} diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/traceur/TraceUtils.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/traceur/TraceUtils.java index 28f04788ccd899082d5dcbb5f329b2a67832ed33..e78427b2997095f45f4f32a98afa254bf193fdf2 100644 --- a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/traceur/TraceUtils.java +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/traceur/TraceUtils.java @@ -7,12 +7,14 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public class TraceUtils { + private static final ObjectMapper objectMapper = new ObjectMapper(); + private TraceUtils() { // private constructor } - public static String getTraceFromTraceur(ObjectMapper objectMapper, Object traceur) { - String trace= ""; + public static String getTraceFromTraceur(Object traceur) { + String trace = ""; try { trace = objectMapper.writeValueAsString(traceur); } catch (JsonProcessingException e) { diff --git a/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/utils/Constants.java b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/utils/Constants.java new file mode 100644 index 0000000000000000000000000000000000000000..0283c2756ed341ea5cab0df780466725a8b7261f --- /dev/null +++ b/services/calculs/src/main/java/org/mte/numecoeval/calculs/domain/utils/Constants.java @@ -0,0 +1,20 @@ +package org.mte.numecoeval.calculs.domain.utils; + +import java.util.List; + +public class Constants { + + public static final String ELECTRICITY_MIX_CATEGORY = "electricity-mix"; + public static final String CATEGORIE_RESEAU_FIXE = "RESEAU_FIXE"; + public static final String CATEGORIE_RESEAU_MOBILE = "RESEAU_MOBILE"; + public static final String CATEGORIE_BATIMENT = "BATIMENT"; + public static final String CATEGORIE_MAINTENANCE = "MAINTENANCE"; + public static final String CATEGORIE_DEPLACEMENT_ELECTRIQUE = "DEPLACEMENT_ELECTRIQUE"; + public static final String CATEGORIE_DEPLACEMENT_HYBRIDE = "DEPLACEMENT_HYBRIDE"; + public static final String CATEGORIE_DEPLACEMENT_ESSENCE = "DEPLACEMENT_ESSENCE"; + public static final List<String> CATEGORIES_INDIRECT_FABRICATION = List.of( + CATEGORIE_DEPLACEMENT_HYBRIDE, + CATEGORIE_DEPLACEMENT_ESSENCE + ); + +} diff --git a/services/calculs/src/test/java/org/mte/numecoeval/calculs/TestJsonUtils.java b/services/calculs/src/test/java/org/mte/numecoeval/calculs/TestJsonUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..43590feacf1cefc18c49138fe0c89cb82b885090 --- /dev/null +++ b/services/calculs/src/test/java/org/mte/numecoeval/calculs/TestJsonUtils.java @@ -0,0 +1,19 @@ +package org.mte.numecoeval.calculs; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class TestJsonUtils { + public static String format(String json) { + var mapper = new ObjectMapper().configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true); + try { + return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(mapper.readValue(json, Object.class)); + } catch (JsonProcessingException e) { + log.error("Cannot format json string", e); + } + return null; + } +} diff --git a/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactApplicationServiceImplTest.java b/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactApplicationServiceImplTest.java index ee8972137ef2d085a1fa861a1a09bc9b88175311..e6acd91211c7e09be1f6bc025806303059c6c728 100644 --- a/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactApplicationServiceImplTest.java +++ b/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactApplicationServiceImplTest.java @@ -1,6 +1,5 @@ package org.mte.numecoeval.calculs.domain.service; -import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -22,16 +21,16 @@ import static org.junit.jupiter.api.Assertions.*; @ExtendWith(MockitoExtension.class) class CalculImpactApplicationServiceImplTest { - CalculImpactApplicationServiceImpl calculImpactApplicatifService ; + CalculImpactApplicationServiceImpl calculImpactApplicatifService; @BeforeEach - void setUp(){ - calculImpactApplicatifService = new CalculImpactApplicationServiceImpl(new ObjectMapper()); + void setUp() { + calculImpactApplicatifService = new CalculImpactApplicationServiceImpl(); } @Test void whenImpactEquipementVirtuelIsInError_ShouldReturnImpactError() { - String applicationName ="MS-Word"; + String applicationName = "MS-Word"; String environnement = "Production"; LocalDate dateLot = LocalDate.of(2023, 4, 1); Application application = Application.builder() @@ -80,7 +79,7 @@ class CalculImpactApplicationServiceImplTest { @Test void whenImpactEquipementVirtuelIsNull_ShouldReturnImpactError() { - String applicationName ="MS-Word"; + String applicationName = "MS-Word"; String environnement = "Production"; LocalDate dateLot = LocalDate.of(2023, 4, 1); Application application = Application.builder() @@ -130,7 +129,7 @@ class CalculImpactApplicationServiceImplTest { @ParameterizedTest @ValueSource(ints = 0) void whenNbApplicationIs0_ShouldApplyRatio1AndReturnImpactOK(Integer nbApplications) { - String applicationName ="MS-Word"; + String applicationName = "MS-Word"; String environnement = "Production"; LocalDate dateLot = LocalDate.of(2023, 4, 1); Application application = Application.builder() @@ -178,7 +177,7 @@ class CalculImpactApplicationServiceImplTest { @ParameterizedTest @NullSource void whenNbApplicationIsNull_ShouldApplyRatio1AndReturnImpactOK(Integer nbApplications) { - String applicationName ="MS-Word"; + String applicationName = "MS-Word"; String environnement = "Production"; LocalDate dateLot = LocalDate.of(2023, 4, 1); Application application = Application.builder() @@ -225,7 +224,7 @@ class CalculImpactApplicationServiceImplTest { @Test void whenImpactEquipementVirtuelIsOK_ShouldReturnImpactOK() { - String applicationName ="MS-Word"; + String applicationName = "MS-Word"; String environnement = "Production"; LocalDate dateLot = LocalDate.of(2023, 4, 1); Application application = Application.builder() @@ -272,7 +271,7 @@ class CalculImpactApplicationServiceImplTest { @Test void taiga1025_whenNbApplicationsIsMoreThan1_ThenImpactShouldBeDividedAndImpactShouldBeOK() { - String applicationName ="MS-Word"; + String applicationName = "MS-Word"; String environnement = "Production"; LocalDate dateLot = LocalDate.of(2023, 4, 1); Application application = Application.builder() @@ -312,8 +311,8 @@ class CalculImpactApplicationServiceImplTest { assertContentIndicateur(demanceCalcul, impactApplication); - assertEquals(demanceCalcul.getImpactEquipementVirtuel().getImpactUnitaire()/demanceCalcul.getNbApplications(), impactApplication.getImpactUnitaire()); - assertEquals(demanceCalcul.getImpactEquipementVirtuel().getConsoElecMoyenne()/demanceCalcul.getNbApplications(), impactApplication.getConsoElecMoyenne()); + assertEquals(demanceCalcul.getImpactEquipementVirtuel().getImpactUnitaire() / demanceCalcul.getNbApplications(), impactApplication.getImpactUnitaire()); + assertEquals(demanceCalcul.getImpactEquipementVirtuel().getConsoElecMoyenne() / demanceCalcul.getNbApplications(), impactApplication.getConsoElecMoyenne()); assertEquals("OK", impactApplication.getStatutIndicateur()); assertEquals("{\"formule\":\"ImpactApplication = ImpactEquipementVirtuel(61.744) / nbApplications(10)\",\"nbApplications\":10}", impactApplication.getTrace()); diff --git a/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactEquipementPhysiqueServiceTest.java b/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactEquipementPhysiqueServiceTest.java index 7d644ac5b0626e4878ecd18ad61315ace5d535de..38135838120be3bfdbcadfd63a9ebbd9b4fc2e32 100644 --- a/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactEquipementPhysiqueServiceTest.java +++ b/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactEquipementPhysiqueServiceTest.java @@ -7,9 +7,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactEquipementPhysique; +import org.mte.numecoeval.calculs.domain.data.demande.OptionsCalcul; import org.mte.numecoeval.calculs.domain.data.entree.DataCenter; import org.mte.numecoeval.calculs.domain.data.entree.EquipementPhysique; import org.mte.numecoeval.calculs.domain.data.indicateurs.ImpactEquipementPhysique; @@ -55,15 +55,11 @@ class CalculImpactEquipementPhysiqueServiceTest { @Mock private DureeDeVieEquipementPhysiqueServiceImpl dureeDeVieEquipementPhysiqueService; - @Spy - private ObjectMapper objectMapper; - @BeforeEach public void init() throws Exception { MockitoAnnotations.openMocks(this); calculImpactEquipementPhysiqueService = new CalculImpactEquipementPhysiqueServiceImpl( - dureeDeVieEquipementPhysiqueService, - objectMapper + dureeDeVieEquipementPhysiqueService ); etapeACV = "UTILISATION"; String etapeACV = "UTILISATION"; @@ -861,9 +857,10 @@ class CalculImpactEquipementPhysiqueServiceTest { .correspondanceRefEquipement(refEquipement) .typeEquipement(typeEquipement) .impactEquipements(Collections.singletonList(referentielImpactEquipement)) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); - when(dureeDeVieEquipementPhysiqueService.calculerDureeVie(any(DemandeCalculImpactEquipementPhysique.class))).thenReturn(DureeDeVie.builder().valeur(5.0d).build()); + when(dureeDeVieEquipementPhysiqueService.calculerDureeVie(any(DemandeCalculImpactEquipementPhysique.class))).thenReturn(DureeDeVie.builder().valeurRetenue(5.0d).build()); //When var actual = calculImpactEquipementPhysiqueService.calculerImpactEquipementPhysique( @@ -931,8 +928,9 @@ class CalculImpactEquipementPhysiqueServiceTest { .equipementPhysique(equipementPhysique) .correspondanceRefEquipement(refEquipement) .typeEquipement(typeEquipement) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); - when(dureeDeVieEquipementPhysiqueService.calculerDureeVie(any(DemandeCalculImpactEquipementPhysique.class))).thenReturn(DureeDeVie.builder().valeur(6.0).build()); + when(dureeDeVieEquipementPhysiqueService.calculerDureeVie(any(DemandeCalculImpactEquipementPhysique.class))).thenReturn(DureeDeVie.builder().valeurRetenue(6.0).build()); //When var actual = calculImpactEquipementPhysiqueService.calculerImpactEquipementPhysique( @@ -1000,8 +998,9 @@ class CalculImpactEquipementPhysiqueServiceTest { .correspondanceRefEquipement(refEquipement) .typeEquipement(typeEquipement) .impactEquipements(Collections.singletonList(referentielImpactEquipement)) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); - when(dureeDeVieEquipementPhysiqueService.calculerDureeVie(any(DemandeCalculImpactEquipementPhysique.class))).thenReturn(DureeDeVie.builder().valeur(7.0).build()); + when(dureeDeVieEquipementPhysiqueService.calculerDureeVie(any(DemandeCalculImpactEquipementPhysique.class))).thenReturn(DureeDeVie.builder().valeurRetenue(7.0).build()); //When var actual = calculImpactEquipementPhysiqueService.calculerImpactEquipementPhysique( @@ -1137,14 +1136,14 @@ class CalculImpactEquipementPhysiqueServiceTest { var formule = TraceCalculImpactEquipementPhysiqueUtils.getFormulePremierScenario(3d, 200d, 150d, 1.0); - var consoElecAnMoyenne = ConsoElecAnMoyenne.builder().valeurEquipementConsoElecAnnuelle(200d).valeur(200d).build(); + var consoElecAnMoyenne = ConsoElecAnMoyenne.builder().valeurItemConsoElecAnnuelle(200d).valeur(200d).build(); var mixElectrique = MixElectrique.builder().valeur(150d).valeurReferentielMixElectrique(150d).sourceReferentielMixElectrique("Source-Mix").build(); TraceCalculImpactEquipementPhysique trace = TraceCalculImpactEquipementPhysique.builder() .formule(formule) .consoElecAnMoyenne(consoElecAnMoyenne) .mixElectrique(mixElectrique) .build(); - var expected = objectMapper.writeValueAsString(trace); + var expected = new ObjectMapper().writeValueAsString(trace); //WHEN var actual = calculImpactEquipementPhysiqueService.calculerImpactEquipementPhysique(demandeCalcul); //THEN @@ -1211,7 +1210,7 @@ class CalculImpactEquipementPhysiqueServiceTest { var consoElecAnMoyenne = ConsoElecAnMoyenne.builder() .valeur(130d) .valeurReferentielConsoElecMoyenne(130d) - .sourceReferentielImpactEquipement("source-RefEquipement") + .sourceReferentielFacteurCaracterisation("source-RefEquipement") .build(); var mixElectrique = MixElectrique.builder() .valeur(125d) @@ -1225,7 +1224,7 @@ class CalculImpactEquipementPhysiqueServiceTest { .consoElecAnMoyenne(consoElecAnMoyenne) .mixElectrique(mixElectrique) .build(); - var expected = objectMapper.writeValueAsString(trace); + var expected = new ObjectMapper().writeValueAsString(trace); //WHEN var actual = calculImpactEquipementPhysiqueService.calculerImpactEquipementPhysique(demandeCalcul); //THEN @@ -1283,6 +1282,7 @@ class CalculImpactEquipementPhysiqueServiceTest { .correspondanceRefEquipement(refEquipement) .typeEquipement(typeEquipement) .impactEquipements(Collections.singletonList(referentielImpactEquipement)) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); @@ -1290,7 +1290,10 @@ class CalculImpactEquipementPhysiqueServiceTest { var valeurDureeVie = ChronoUnit.DAYS.between(dateAchat, dateRetrait) / 365d; DureeDeVie dureeDeVie = DureeDeVie.builder() - .valeur(valeurDureeVie) + .valeurRetenue(valeurDureeVie) + .methodeDureeUsage("REEL") + .dureeUsageAmont(0.0) + .dureeUsageAval(0.0) .dateAchat(dateAchat.format(DateTimeFormatter.ISO_DATE)) .dateRetrait(dateRetrait.format(DateTimeFormatter.ISO_DATE)) .build(); @@ -1303,7 +1306,7 @@ class CalculImpactEquipementPhysiqueServiceTest { .valeurReferentielImpactEquipement(valeurRefrentiel) .sourceReferentielImpactEquipement(sourceReferentielImpactEquipement) .build(); - var expected = objectMapper.writeValueAsString(trace); + var expected = new ObjectMapper().writeValueAsString(trace); //WHEN var actual = calculImpactEquipementPhysiqueService.calculerImpactEquipementPhysique(demandeCalcul); @@ -1358,9 +1361,10 @@ class CalculImpactEquipementPhysiqueServiceTest { .correspondanceRefEquipement(refEquipement) .typeEquipement(typeEquipement) .impactEquipements(Collections.singletonList(referentielImpactEquipement)) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); - when(dureeDeVieEquipementPhysiqueService.calculerDureeVie(any(DemandeCalculImpactEquipementPhysique.class))).thenReturn(DureeDeVie.builder().valeur(7.0).build()); + when(dureeDeVieEquipementPhysiqueService.calculerDureeVie(any(DemandeCalculImpactEquipementPhysique.class))).thenReturn(DureeDeVie.builder().valeurRetenue(7.0).build()); //When var actual = calculImpactEquipementPhysiqueService.calculerImpactEquipementPhysique( @@ -1429,9 +1433,10 @@ class CalculImpactEquipementPhysiqueServiceTest { .correspondanceRefEquipement(refEquipement) .typeEquipement(typeEquipement) .impactEquipements(Collections.singletonList(referentielImpactEquipement)) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); - when(dureeDeVieEquipementPhysiqueService.calculerDureeVie(any(DemandeCalculImpactEquipementPhysique.class))).thenReturn(DureeDeVie.builder().valeur(7.0).build()); + when(dureeDeVieEquipementPhysiqueService.calculerDureeVie(any(DemandeCalculImpactEquipementPhysique.class))).thenReturn(DureeDeVie.builder().valeurRetenue(7.0).build()); //When var actual = calculImpactEquipementPhysiqueService.calculerImpactEquipementPhysique( @@ -1509,6 +1514,7 @@ class CalculImpactEquipementPhysiqueServiceTest { .correspondanceRefEquipement(refEquipement) .typeEquipement(typeEquipement) .impactEquipements(Collections.singletonList(referentielImpactEquipement)) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); //When @@ -2223,8 +2229,9 @@ class CalculImpactEquipementPhysiqueServiceTest { .typeEquipement(typeEquipement) .hypotheses(Collections.singletonList(referentielHypothese)) .impactEquipements(Collections.singletonList(referentielImpactEquipement)) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); - when(dureeDeVieEquipementPhysiqueService.calculerDureeVie(any(DemandeCalculImpactEquipementPhysique.class))).thenReturn(DureeDeVie.builder().valeur(5.0d).build()); + when(dureeDeVieEquipementPhysiqueService.calculerDureeVie(any(DemandeCalculImpactEquipementPhysique.class))).thenReturn(DureeDeVie.builder().valeurRetenue(5.0d).build()); //When var actual = calculImpactEquipementPhysiqueService.calculerImpactEquipementPhysique( demandeCalcul diff --git a/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactEquipementVirtuelServiceTest.java b/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactEquipementVirtuelServiceTest.java index c197969a76a39744bf88fc1632fa99791e2b53fd..d5c47b612f4bdfc90c0ee11b0a2d2847fa5fd78f 100644 --- a/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactEquipementVirtuelServiceTest.java +++ b/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactEquipementVirtuelServiceTest.java @@ -5,7 +5,6 @@ import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactEquipementVirtuel; import org.mte.numecoeval.calculs.domain.data.entree.EquipementVirtuel; @@ -26,13 +25,11 @@ import static org.junit.jupiter.api.Assertions.*; @ExtendWith({MockitoExtension.class, OutputCaptureExtension.class}) class CalculImpactEquipementVirtuelServiceTest { - @Spy - private ObjectMapper objectMapper; private CalculImpactEquipementVirtuelService calculImpactEquipementVirtuelService; @BeforeEach void setUp() { - calculImpactEquipementVirtuelService = new CalculImpactEquipementVirtuelServiceImpl(objectMapper); + calculImpactEquipementVirtuelService = new CalculImpactEquipementVirtuelServiceImpl(); } /** @@ -46,7 +43,7 @@ class CalculImpactEquipementVirtuelServiceTest { //GIVEN EquipementVirtuel equipementVirtuel1 = EquipementVirtuel.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -96,7 +93,7 @@ class CalculImpactEquipementVirtuelServiceTest { void whenTotalVCPUIsNull_shouldReturnCalculImpactUsingTotalNumberOfVirtualEquipment() { //GIVEN EquipementVirtuel equipementVirtuel1 = EquipementVirtuel.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -145,7 +142,7 @@ class CalculImpactEquipementVirtuelServiceTest { void whenTypeEqvIsNotCalculAndTotalVCPUIsNull_shouldReturnCalculImpactUsingTotalNumberOfVirtualEquipment() { //GIVEN EquipementVirtuel equipementVirtuel1 = EquipementVirtuel.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -193,7 +190,7 @@ class CalculImpactEquipementVirtuelServiceTest { @Test void whenTotalVCPUAndNbrVirtualEquipementAreNull_shouldReturnImpactError() { EquipementVirtuel equipementVirtuel = EquipementVirtuel.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -230,7 +227,7 @@ class CalculImpactEquipementVirtuelServiceTest { void whenNbrVirtualEquipementIs0_shouldReturnImpactError() { //GIVEN EquipementVirtuel equipementVirtuel1 = EquipementVirtuel.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -277,7 +274,7 @@ class CalculImpactEquipementVirtuelServiceTest { //GIVEN EquipementVirtuel equipementVirtuel1 = EquipementVirtuel.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -324,7 +321,7 @@ class CalculImpactEquipementVirtuelServiceTest { //GIVEN EquipementVirtuel equipementVirtuel1 = EquipementVirtuel.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -371,7 +368,7 @@ class CalculImpactEquipementVirtuelServiceTest { void caf5() { EquipementVirtuel equipementVirtuel1 = EquipementVirtuel.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -409,7 +406,7 @@ class CalculImpactEquipementVirtuelServiceTest { void shouldGetTraceCalculVm() throws Exception { //GIVEN EquipementVirtuel equipementVirtuel1 = EquipementVirtuel.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -434,13 +431,13 @@ class CalculImpactEquipementVirtuelServiceTest { .equipementVirtuel(equipementVirtuel1) .impactEquipement(impactEquipementPhysique) .nbEquipementsVirtuels(3) - .nbTotalVCPU(7+3+9) + .nbTotalVCPU(7 + 3 + 9) .build(); //WHEN var impactEquipementVirtuel = calculImpactEquipementVirtuelService.calculerImpactEquipementVirtuel(demandeCalcul); var formule = TraceCalculImpactVirtuelUtils.getFormuleWithTotalVCPU(demandeCalcul); - var expected = objectMapper.writeValueAsString(TraceCalculImpactEquipementVirtuel.builder() + var expected = new ObjectMapper().writeValueAsString(TraceCalculImpactEquipementVirtuel.builder() .nbTotalVCPU(demandeCalcul.getNbTotalVCPU()) .nbEquipementsVirtuels(demandeCalcul.getNbEquipementsVirtuels()) .formule(formule) @@ -456,7 +453,7 @@ class CalculImpactEquipementVirtuelServiceTest { void forTaiga437VM1_shouldReturnCalculImpactUsingProrataFormula() { //GIVEN EquipementVirtuel equipementVirtuel1 = EquipementVirtuel.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -503,7 +500,7 @@ class CalculImpactEquipementVirtuelServiceTest { void forTaiga437VM2_shouldReturnCalculImpactUsingProrataOnCPUFormula() { //GIVEN EquipementVirtuel equipementVirtuel1 = EquipementVirtuel.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -553,7 +550,7 @@ class CalculImpactEquipementVirtuelServiceTest { void forTaiga437VM4_shouldReturnCalculImpactUsingProrataFormula() { //GIVEN EquipementVirtuel equipementVirtuel1 = EquipementVirtuel.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -565,7 +562,7 @@ class CalculImpactEquipementVirtuelServiceTest { .cleRepartition(null) .build(); EquipementVirtuel equipementVirtuel2 = EquipementVirtuel.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -577,7 +574,7 @@ class CalculImpactEquipementVirtuelServiceTest { .cleRepartition(null) .build(); EquipementVirtuel equipementVirtuel3 = EquipementVirtuel.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") diff --git a/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactMessagerieServiceTest.java b/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactMessagerieServiceTest.java index 55c55784afca89f3a94aa202ddbcf5bf6dfeb0fc..0835c7da2c0a5158c0f8e1a7439b1267ec872655 100644 --- a/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactMessagerieServiceTest.java +++ b/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactMessagerieServiceTest.java @@ -1,6 +1,5 @@ package org.mte.numecoeval.calculs.domain.service; -import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.Test; import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactMessagerie; import org.mte.numecoeval.calculs.domain.data.entree.Messagerie; @@ -18,10 +17,10 @@ import static org.junit.jupiter.api.Assertions.*; class CalculImpactMessagerieServiceTest { - ObjectMapper objectMapper = new ObjectMapper(); - CalculImpactMessagerieService calculImpactMessagerieService = new CalculImpactMessagerieServiceImpl(objectMapper); + CalculImpactMessagerieService calculImpactMessagerieService = new CalculImpactMessagerieServiceImpl(); + @Test - void whenValidMessagerie_shoudCalculerImpactMessagerie(){ + void whenValidMessagerie_shoudCalculerImpactMessagerie() { //GIVEN var dateCalcul = LocalDateTime.now(); ReferentielCritere critere = ReferentielCritere.builder() @@ -35,7 +34,7 @@ class CalculImpactMessagerieServiceTest { .constanteCoefficientDirecteur(30d) .build(); var messagerie = Messagerie.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -57,13 +56,13 @@ class CalculImpactMessagerieServiceTest { //THEN assertContentIndicateur(demandeCalcul, impactMessagerie); - assertEquals(468000d , impactMessagerie.getImpactMensuel()); + assertEquals(468000d, impactMessagerie.getImpactMensuel()); assertEquals("OK", impactMessagerie.getStatutIndicateur()); assertEquals("{\"critere\":\"Changement Climatique\",\"volumeTotalMailEmis\":5000.0,\"nombreMailEmis\":300.0,\"constanteCoefficientDirecteur\":30.0,\"poidsMoyenMail\":16.666666666666668,\"constanteOrdonneeOrigine\":20.0,\"nombreMailEmisXDestinataires\":900.0,\"formule\":\"poidsMoyenMail(16.666666666666668) = volumeTotalMailEmis(5000.0)/nombreMailEmis(300.0);\\nimpactMensuel = (constanteCoefficientDirecteur (30.0) * poidsMoyenMail(16.666666666666668) + constanteOrdonneeOrigine(20.0)) * nombreMailEmisXDestinataires(900.0)\\n\"}", impactMessagerie.getTrace()); } @Test - void whenNonValidMessagerie_shouldReturnEmptyResult(){ + void whenNonValidMessagerie_shouldReturnEmptyResult() { var dateCalcul = LocalDateTime.now(); @@ -78,7 +77,7 @@ class CalculImpactMessagerieServiceTest { .constanteCoefficientDirecteur(30d) .build(); var messagerie = Messagerie.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -103,7 +102,7 @@ class CalculImpactMessagerieServiceTest { } @Test - void whenReferentielIsNotFound_shouldReturnEmptyResult(){ + void whenReferentielIsNotFound_shouldReturnEmptyResult() { var dateCalcul = LocalDateTime.now(); @@ -112,7 +111,7 @@ class CalculImpactMessagerieServiceTest { .unite("kg CO_{2} eq") .build(); var messagerie = Messagerie.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") diff --git a/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactOperationNonITServiceTest.java b/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactOperationNonITServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e9340db028c3166bec2728721e8cece2ed24ae7c --- /dev/null +++ b/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactOperationNonITServiceTest.java @@ -0,0 +1,1321 @@ +package org.mte.numecoeval.calculs.domain.service; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; +import org.mte.numecoeval.calculs.TestJsonUtils; +import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactOperationNonIT; +import org.mte.numecoeval.calculs.domain.data.indicateurs.ImpactOperationNonIT; +import org.mte.numecoeval.calculs.domain.data.referentiel.ReferentielFacteurCaracterisation; +import org.mte.numecoeval.calculs.domain.data.referentiel.ReferentielHypothese; +import org.mte.numecoeval.calculs.domain.data.referentiel.ReferentielTypeItem; +import org.mte.numecoeval.calculs.domain.exception.CalculImpactException; +import org.mte.numecoeval.calculs.domain.port.input.service.CalculImpactOperationNonITService; +import org.mte.numecoeval.calculs.domain.port.input.service.impl.CalculImpactOperationNonITServiceImpl; + +import java.time.LocalDateTime; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + + +class CalculImpactOperationNonITServiceTest { + + CalculImpactOperationNonITService calculImpactOperationNonITService = new CalculImpactOperationNonITServiceImpl(); + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + private DemandeCalculImpactOperationNonIT createDemande() { + try { + var res = objectMapper.readValue(""" + { + "operationNonIT": { + "nomItemNonIT": "nomItem", + "quantite": 1.0, + "localisation": "France", + "nomEntite": "nomEntite" + }, + "etape": { + "code": "FABRICATION" + }, + "critere": { + "nomCritere": "Changement Climatique", + "unite": "kg CO_{2} eq" + }, + "typeItem": {}, + "hypotheses": [], + "facteurCaracterisations": [] + } + """, DemandeCalculImpactOperationNonIT.class); + res.setDateCalcul(LocalDateTime.parse("2024-01-01T00:00:00")); + return res; + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + /** + * Tests de la fonction getDureeVie() + */ + @Test + void shouldCalculerDureeDeVie_fromInventaire() throws CalculImpactException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getOperationNonIT().setType("Batiment non DC"); + demandeCalcul.getOperationNonIT().setDureeDeVie(2.0); + + // When + var actual = calculImpactOperationNonITService.getDureeVie(demandeCalcul); + + // Then + assertEquals(2.0, actual.getValeurRetenue(), 2.0); + assertNull(actual.getDureeDeVieParDefaut()); + } + + @Test + void shouldCalculerDureeDeVie_fromInventaireInf1() throws CalculImpactException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getOperationNonIT().setType("Batiment non DC"); + demandeCalcul.getOperationNonIT().setDureeDeVie(0.6); + + // When + var actual = calculImpactOperationNonITService.getDureeVie(demandeCalcul); + + // Then + assertEquals(1.0, actual.getValeurRetenue(), 2.0); + } + + @Test + void shouldCalculerDureeDeVie_fromTypeItem() throws JsonProcessingException, CalculImpactException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getOperationNonIT().setType("Batiment non DC"); + + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "Batiment non DC", + "categorie": "BATIMENT", + "dureeVieDefaut": "3.0", + "refItemParDefaut": "batiment-fr", + "source": "source" + } + """, ReferentielTypeItem.class)); + demandeCalcul.setHypotheses(List.of(objectMapper.readValue(""" + [ + { + "code": "dureeVieBatimentParDefaut", + "valeur": "10.0", + "source": "sourceDefault" + } + ] + """, ReferentielHypothese[].class))); + // When + var actual = calculImpactOperationNonITService.getDureeVie(demandeCalcul); + + // Then + assertEquals(3.0, actual.getValeurRetenue(), 2.0); + assertEquals(3.0, actual.getDureeDeVieParDefaut().getValeurTypeItemDureeVieDefaut(), 2.0); + assertEquals("source", actual.getDureeDeVieParDefaut().getSourceTypeItemDureeVieDefaut()); + } + + @Test + void shouldCalculerDureeDeVie_fromTypeItemInf1() throws JsonProcessingException, CalculImpactException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getOperationNonIT().setType("Batiment non DC"); + + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "Batiment non DC", + "categorie": "BATIMENT", + "dureeVieDefaut": "0.6", + "refItemParDefaut": "batiment-fr", + "source": "source" + } + """, ReferentielTypeItem.class)); + // When + var actual = calculImpactOperationNonITService.getDureeVie(demandeCalcul); + + // Then + assertEquals(1.0, actual.getValeurRetenue(), 2.0); + assertEquals(0.6, actual.getDureeDeVieParDefaut().getValeurTypeItemDureeVieDefaut(), 2.0); + assertEquals("source", actual.getDureeDeVieParDefaut().getSourceTypeItemDureeVieDefaut()); + } + + @Test + void shouldCalculerDureeDeVie_fromHypothese() throws JsonProcessingException, CalculImpactException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getOperationNonIT().setType("Batiment non DC"); + + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "Batiment non DC", + "categorie": "BATIMENT", + "refItemParDefaut": "batiment-fr", + "source": "source" + } + """, ReferentielTypeItem.class)); + demandeCalcul.setHypotheses(List.of(objectMapper.readValue(""" + [ + { + "code": "dureeVieBatimentParDefaut", + "valeur": "10.0", + "source": "sourceDefault" + } + ] + """, ReferentielHypothese[].class))); + // When + var actual = calculImpactOperationNonITService.getDureeVie(demandeCalcul); + + // Then + assertEquals(10.0, actual.getValeurRetenue(), 2.0); + assertEquals(10.0, actual.getDureeDeVieParDefaut().getValeurReferentielHypothese(), 2.0); + assertEquals("sourceDefault", actual.getDureeDeVieParDefaut().getSourceReferentielHypothese()); + } + + /** + * Tests de la fonction getFormuleDefaut() + */ + @Test + void shouldCalculerImpactOperationNonIT_reseau_mobile_fabrication() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getOperationNonIT().setType("Reseau Mobile"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "Reseau Mobile", + "categorie": "RESEAU_MOBILE", + "refItemParDefaut": "Reseau Mobile", + "dureeVieDefaut": 10.0 + } + """, ReferentielTypeItem.class)); + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "Reseau Mobile", + "etape": "FABRICATION", + "critere": "Changement Climatique", + "valeur": 10, + "source": "SSG" + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertEquals("OK", actual.getStatutIndicateur()); + assertEquals(10.0, actual.getImpactUnitaire(), 0.0001d); + assertEquals(TestJsonUtils.format(""" + { + "formule" : "ImpactOperationNonIT = (Quantité(1.0) * ReferentielFacteurCaracterisation(10.0))", + "sourceReferentielFacteurCaracterisation" : "SSG", + "valeurReferentielFacteurCaracterisation" : 10.0 + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + /** + * Tests de la fonction getFormuleUtilisationDefaut() + */ + @Test + void shouldCalculerImpactOperationNonIT_reseau_mobile_utilisation_consoElecFromItemNonIT() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getEtape().setCode("UTILISATION"); + demandeCalcul.getOperationNonIT().setType("Reseau Mobile"); + demandeCalcul.getOperationNonIT().setConsoElecAnnuelle(100.0); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "Reseau Mobile", + "categorie": "RESEAU_MOBILE", + "refItemParDefaut": "Reseau Mobile", + "dureeVieDefaut": 10.0 + } + """, ReferentielTypeItem.class)); + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "Reseau Mobile", + "etape": "UTILISATION", + "critere": "Changement Climatique", + "valeur": 10, + "source": "SSG" + }, + { + "nom": "Electricty Mix FR", + "etape": "FABRICATION", + "critere": "Changement Climatique", + "categorie" : "electricity-mix", + "localisation": "France", + "valeur" : 0.01 + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertEquals("OK", actual.getStatutIndicateur()); + assertEquals(1.0, actual.getImpactUnitaire(), 0.0001d); + assertEquals(demandeCalcul.getOperationNonIT().getConsoElecAnnuelle(), actual.getConsoElecMoyenne()); + assertEquals(TestJsonUtils.format(""" + { + "consoElecAnMoyenne" : { + "valeur" : 100.0, + "valeurItemConsoElecAnnuelle" : 100.0 + }, + "formule" : "ImpactOperationNonIT = (Quantité(1.0) * ConsoElecAnMoyenne(100.0) * MixElectrique(0.01))", + "mixElectrique" : { + "serveur" : false, + "valeur" : 0.01, + "valeurReferentielMixElectrique" : 0.01 + } + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + @Test + void shouldCalculerImpactOperationNonIT_reseau_mobile_utilisation_consoElecFromFacteurCaracterisation() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getEtape().setCode("UTILISATION"); + demandeCalcul.getOperationNonIT().setType("Reseau Mobile"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "Reseau Mobile", + "categorie": "RESEAU_MOBILE", + "refItemParDefaut": "Reseau Mobile", + "dureeVieDefaut": 10.0 + } + """, ReferentielTypeItem.class)); + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "Reseau Mobile", + "etape": "UTILISATION", + "critere": "Changement Climatique", + "consoElecMoyenne": 100.0, + "valeur": 10, + "source": "SSG" + }, + { + "nom": "Electricty Mix FR", + "etape": "FABRICATION", + "critere": "Changement Climatique", + "categorie" : "electricity-mix", + "localisation": "France", + "valeur" : 0.01 + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertEquals("OK", actual.getStatutIndicateur()); + assertEquals(1.0, actual.getImpactUnitaire(), 0.0001d); + assertEquals(TestJsonUtils.format(""" + { + "consoElecAnMoyenne" : { + "sourceReferentielFacteurCaracterisation" : "SSG", + "valeur" : 100.0, + "valeurReferentielConsoElecMoyenne" : 100.0 + }, + "formule" : "ImpactOperationNonIT = (Quantité(1.0) * ConsoElecAnMoyenne(100.0) * MixElectrique(0.01))", + "mixElectrique" : { + "serveur" : false, + "valeur" : 0.01, + "valeurReferentielMixElectrique" : 0.01 + } + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + @Test + void when_CalculerImpactOperationNonIT_reseau_mobile_Item_NotInFacteurCaracterisation_shouldReturnIndicateurWithError() { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.setTypeItem(ReferentielTypeItem.builder() + .categorie("RESEAU_MOBILE") + .build()); + demandeCalcul.setFacteurCaracterisations(null); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertNull(actual.getImpactUnitaire()); + assertEquals("ERREUR", actual.getStatutIndicateur()); + assertEquals(TestJsonUtils.format( + """ + { + "erreur": "ErrCalcFonc : Référentiel Facteur Caractérisation inconnu" + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + @Test + void when_CalculerImpactOperationNonIT_reseau_mobile_utilisation_And_NoConsoElec_shouldReturnIndicateurWithError() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getEtape().setCode("UTILISATION"); + demandeCalcul.getOperationNonIT().setType("Reseau Mobile"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "Reseau Mobile", + "categorie": "RESEAU_MOBILE", + "refItemParDefaut": "Reseau Mobile", + "dureeVieDefaut": 10.0 + } + """, ReferentielTypeItem.class)); + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "Reseau Mobile", + "etape": "UTILISATION", + "critere": "Changement Climatique", + "valeur": 10, + "source": "SSG" + }, + { + "nom": "Electricty Mix FR", + "etape": "FABRICATION", + "critere": "Changement Climatique", + "categorie" : "electricity-mix", + "localisation": "France", + "valeur" : 0.01 + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertNull(actual.getImpactUnitaire()); + assertEquals("ERREUR", actual.getStatutIndicateur()); + assertEquals(TestJsonUtils.format(""" + { + "erreur" : "ErrCalcFonc : Donnée de consommation electrique manquante : operationNonIT : nomItem, RefItemParDefaut : Reseau Mobile" + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + @Test + void when_CalculerImpactOperationNonIT_reseau_mobile_utilisation_And_MixElecNotInReferentiel_shouldReturnIndicateurWithError() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getEtape().setCode("UTILISATION"); + demandeCalcul.getOperationNonIT().setConsoElecAnnuelle(0.09); + demandeCalcul.getOperationNonIT().setType("Reseau Mobile"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "Reseau Mobile", + "categorie": "RESEAU_MOBILE", + "refItemParDefaut": "Reseau Mobile", + "dureeVieDefaut": 10.0 + } + """, ReferentielTypeItem.class)); + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "Reseau Mobile", + "etape": "UTILISATION", + "critere": "Changement Climatique", + "valeur": 10, + "source": "SSG" + }, + { + "nom": "Electricty Mix FR", + "etape": "FABRICATION", + "critere": "Changement Climatique", + "categorie" : "electricity-mix", + "localisation": "!!! PAYS INCONNU !!!", + "valeur" : 0.01 + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertNull(actual.getImpactUnitaire()); + assertEquals("ERREUR", actual.getStatutIndicateur()); + assertEquals(TestJsonUtils.format(""" + { + "erreur" : "ErrCalcFonc : Il n'existe pas de Mix électrique pour cet item non it : critere: Changement Climatique - operation non it: nomItem - Localisation: France" + } + """), + TestJsonUtils.format(actual.getTrace())); + + } + + @Test + void shouldCalculerImpactOperationNonIT_maintenance_fabrication() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getOperationNonIT().setType("Maintenance sur facture"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "Maintenance sur facture", + "categorie": "MAINTENANCE", + "refItemParDefaut": "maintenance-1", + "source": "sourceDefault" + } + """, ReferentielTypeItem.class)); + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "maintenance-1", + "etape": "FABRICATION", + "critere": "Changement Climatique", + "valeur": 10, + "source": "sourceDefault" + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertEquals("OK", actual.getStatutIndicateur()); + assertEquals(10.0, actual.getImpactUnitaire(), 0.0001d); + assertEquals(TestJsonUtils.format( + """ + { + "formule" : "ImpactOperationNonIT = (Quantité(1.0) * ReferentielFacteurCaracterisation(10.0))", + "sourceReferentielFacteurCaracterisation" : "sourceDefault", + "valeurReferentielFacteurCaracterisation" : 10.0 + } + """), + TestJsonUtils.format(actual.getTrace())); + + } + + @Test + void shouldCalculerImpactOperationNonIT_maintenance_utilisation_consoElecFromItemNonIT() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getEtape().setCode("UTILISATION"); + demandeCalcul.getOperationNonIT().setConsoElecAnnuelle(100.0); + demandeCalcul.getOperationNonIT().setType("Maintenance sur facture"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "Maintenance sur facture", + "categorie": "MAINTENANCE", + "refItemParDefaut": "maintenance-1", + "source": "sourceDefault" + } + """, ReferentielTypeItem.class)); + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "maintenance-1", + "etape": "UTILISATION", + "critere": "Changement Climatique", + "consoElecMoyenne": 100.0, + "valeur": 10, + "source": "sourceDefault" + }, + { + "nom": "Electricty Mix FR", + "etape": "FABRICATION", + "critere": "Changement Climatique", + "categorie" : "electricity-mix", + "localisation": "France", + "valeur" : 0.01 + } + ] + """, ReferentielFacteurCaracterisation[].class))); + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertEquals("OK", actual.getStatutIndicateur()); + assertEquals(1.0, actual.getImpactUnitaire(), 0.0001d); + assertEquals(TestJsonUtils.format(""" + { + "consoElecAnMoyenne" : { + "valeur" : 100.0, + "valeurItemConsoElecAnnuelle" : 100.0 + }, + "formule" : "ImpactOperationNonIT = (Quantité(1.0) * ConsoElecAnMoyenne(100.0) * MixElectrique(0.01))", + "mixElectrique" : { + "serveur" : false, + "valeur" : 0.01, + "valeurReferentielMixElectrique" : 0.01 + } + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + /** + * Tests de la fonction getFormuleReseauFixe() + */ + @Test + void shouldCalculerImpactOperationNonIT_reseau_fixe_fabrication() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getOperationNonIT().setType("Fixed Line FR"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "Fixed Line FR", + "categorie": "RESEAU_FIXE", + "refHypothese": "CAPACITE_LIGNE_FIXE_FR", + "refItemParDefaut": "fixed-line-network-1", + "source": "sourceDefault" + } + """, ReferentielTypeItem.class)); + + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "fixed-line-network-1", + "etape": "FABRICATION", + "critere": "Changement Climatique", + "valeur" : 0.01 + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + demandeCalcul.setHypotheses(List.of(objectMapper.readValue(""" + [ + { + "code": "CAPACITE_LIGNE_FIXE_FR", + "valeur": "10.0", + "source": "sourceDefault" + } + ] + """, ReferentielHypothese[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertEquals("OK", actual.getStatutIndicateur()); + assertEquals(0.001, actual.getImpactUnitaire(), 0.0001d); + assertEquals(TestJsonUtils.format(""" + { + "formule" : "ImpactOperationNonIT = (Quantité(1.0) * ReferentielFacteurCaracterisation(0.01)) / CapaciteLigneFixe(10.0)", + "hypothese" : { + "nom_hypothese" : "CAPACITE_LIGNE_FIXE_FR", + "source" : "sourceDefault", + "valeur" : 10.0 + }, + "valeurReferentielFacteurCaracterisation" : 0.01 + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + @Test + void shouldCalculerImpactOperationNonIT_reseau_fixe_utilisation_consoElecFromFacteurCaracterisation() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getEtape().setCode("UTILISATION"); + demandeCalcul.getOperationNonIT().setType("Fixed Line FR"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "Fixed Line FR", + "categorie": "RESEAU_FIXE", + "refHypothese": "CAPACITE_LIGNE_FIXE_FR", + "refItemParDefaut": "fixed-line-network-1", + "source": "sourceDefault" + } + """, ReferentielTypeItem.class)); + + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "fixed-line-network-1", + "etape": "UTILISATION", + "critere": "Changement Climatique", + "consoElecMoyenne": 100.0, + "valeur" : 0.01 + }, + { + "nom": "Electricty Mix FR", + "etape": "FABRICATION", + "critere": "Changement Climatique", + "categorie" : "electricity-mix", + "localisation": "France", + "valeur" : 0.01 + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + demandeCalcul.setHypotheses(List.of(objectMapper.readValue(""" + [ + { + "code": "CAPACITE_LIGNE_FIXE_FR", + "valeur": "10.0", + "source": "sourceDefault" + } + ] + """, ReferentielHypothese[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertEquals("OK", actual.getStatutIndicateur()); + assertEquals(0.1, actual.getImpactUnitaire(), 0.0001d); + assertEquals(TestJsonUtils.format( + """ + { + "consoElecAnMoyenne" : { + "valeur" : 100.0, + "valeurReferentielConsoElecMoyenne" : 100.0 + }, + "formule" : "ImpactOperationNonIT = (Quantité(1.0) * ConsoElecAnMoyenne(100.0) * MixElectrique(0.01)) / CapaciteLigneFixe(10.0)", + "hypothese" : { + "nom_hypothese" : "CAPACITE_LIGNE_FIXE_FR", + "source" : "sourceDefault", + "valeur" : 10.0 + }, + "mixElectrique" : { + "serveur" : false, + "valeur" : 0.01, + "valeurReferentielMixElectrique" : 0.01 + } + } + """), + TestJsonUtils.format(actual.getTrace()) + ); + } + + /** + * Tests de la fonction getFormuleBatiment() + */ + @Test + void shouldCalculerImpactOperationNonIT_batiment_fabrication_DureeDeVieFromOperationNonIT() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getOperationNonIT().setType("batiment-1"); + demandeCalcul.getOperationNonIT().setDureeDeVie(10.0); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "batiment-1", + "categorie": "BATIMENT", + "refItemParDefaut": "batiment-1", + "source": "sourceDefault" + } + """, ReferentielTypeItem.class)); + + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "batiment-1", + "etape": "FABRICATION", + "critere": "Changement Climatique", + "valeur" : 0.1 + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT( + demandeCalcul + ); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertEquals("OK", actual.getStatutIndicateur()); + assertEquals(0.01, actual.getImpactUnitaire(), 0.0001d); + assertEquals(TestJsonUtils.format(""" + { + "dureeDeVie" : { + "valeurRetenue" : 10.0 + }, + "formule" : "ImpactOperationNonIT = (Quantité(1.0) * ReferentielFacteurCaracterisation(0.1)) / DureeDeVie(10.0)", + "valeurReferentielFacteurCaracterisation" : 0.1 + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + @Test + void shouldCalculerImpactOperationNonIT_batiment_fabrication_DureeDeVieFromTypeItem() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getOperationNonIT().setType("batiment-1"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "batiment-1", + "categorie": "BATIMENT", + "refItemParDefaut": "batiment-1", + "dureeVieDefaut": 30.0, + "source": "sourceDefault" + } + """, ReferentielTypeItem.class)); + + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "batiment-1", + "etape": "FABRICATION", + "critere": "Changement Climatique", + "valeur" : 0.1 + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT( + demandeCalcul + ); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertEquals("OK", actual.getStatutIndicateur()); + assertEquals(0.0033333333333333335, actual.getImpactUnitaire(), 0.0001d); + assertEquals(TestJsonUtils.format(""" + { + "dureeDeVie" : { + "dureeDeVieParDefaut" : { + "sourceTypeItemDureeVieDefaut" : "sourceDefault", + "valeur" : 30.0, + "valeurTypeItemDureeVieDefaut" : 30.0 + }, + "valeurRetenue" : 30.0 + }, + "formule" : "ImpactOperationNonIT = (Quantité(1.0) * ReferentielFacteurCaracterisation(0.1)) / DureeDeVie(30.0)", + "valeurReferentielFacteurCaracterisation" : 0.1 + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + @Test + void shouldCalculerImpactOperationNonIT_batiment_fabrication_DureeDeVieFromHypothese() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getOperationNonIT().setType("batiment-1"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "batiment-1", + "categorie": "BATIMENT", + "refItemParDefaut": "batiment-1", + "source": "sourceDefault" + } + """, ReferentielTypeItem.class)); + + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "batiment-1", + "etape": "FABRICATION", + "critere": "Changement Climatique", + "valeur" : 0.1 + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + demandeCalcul.setHypotheses(List.of(objectMapper.readValue(""" + [ + { + "code": "dureeVieBatimentParDefaut", + "valeur": "50.0", + "source": "sourceDefault" + } + ] + """, ReferentielHypothese[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertEquals("OK", actual.getStatutIndicateur()); + assertEquals(0.002, actual.getImpactUnitaire(), 0.0001d); + assertEquals(TestJsonUtils.format(""" + { + "dureeDeVie" : { + "dureeDeVieParDefaut" : { + "sourceReferentielHypothese" : "sourceDefault", + "valeur" : 50.0, + "valeurReferentielHypothese" : 50.0 + }, + "valeurRetenue" : 50.0 + }, + "formule" : "ImpactOperationNonIT = (Quantité(1.0) * ReferentielFacteurCaracterisation(0.1)) / DureeDeVie(50.0)", + "valeurReferentielFacteurCaracterisation" : 0.1 + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + @Test + void calculImpactOperationNonIT_batiment_utilisation_shouldReturnNull() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getEtape().setCode("UTILISATION"); + demandeCalcul.getOperationNonIT().setType("batiment-1"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "batiment-1", + "categorie": "BATIMENT", + "refItemParDefaut": "batiment-1", + "source": "sourceDefault" + } + """, ReferentielTypeItem.class)); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertNull(actual); + } + + /** + * Tests de la fonction getFormuleDeplacement() + */ + @Test + void shouldCalculerImpactOperationNonIT_deplacementEssence_utilisation() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getEtape().setCode("UTILISATION"); + demandeCalcul.getOperationNonIT().setType("deplacement-voiture-essence"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "deplacement-voiture-essence", + "categorie": "DEPLACEMENT_ESSENCE", + "refHypothese": "CONSO_MOYENNE_VOITURE_ESSENCE", + "refItemParDefaut": "fuel", + "source": "sourceDefault" + } + """, ReferentielTypeItem.class)); + + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "fuel", + "etape": "FABRICATION", + "critere": "Changement Climatique", + "valeur": 0.1 + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + demandeCalcul.setHypotheses(List.of(objectMapper.readValue(""" + [ + { + "code": "CONSO_MOYENNE_VOITURE_ESSENCE", + "valeur": "6.5", + "source": "sourceDefault" + } + ] + """, ReferentielHypothese[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT( + demandeCalcul + ); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertEquals("OK", actual.getStatutIndicateur()); + assertEquals(0.65, actual.getImpactUnitaire(), 0.0001d); + assertEquals(TestJsonUtils.format(""" + { + "formule" : "ImpactOperationNonIT = (ConsoMoyenne(6.5) * NbKmParcourus(1.0) * ReferentielFacteurCaracterisation(0.1))", + "hypothese" : { + "nom_hypothese" : "CONSO_MOYENNE_VOITURE_ESSENCE", + "source" : "sourceDefault", + "valeur" : 6.5 + }, + "valeurReferentielFacteurCaracterisation" : 0.1 + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + @Test + void shouldCalculerImpactOperationNonIT_deplacementEssence_utilisation_withoutFacteurCaracterisation_shouldReturnIndicateurWithError() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getEtape().setCode("UTILISATION"); + demandeCalcul.getOperationNonIT().setType("deplacement-voiture-essence"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "deplacement-voiture-essence", + "categorie": "DEPLACEMENT_ESSENCE", + "refHypothese": "CONSO_MOYENNE_VOITURE_ESSENCE", + "refItemParDefaut": "fuel", + "source": "sourceDefault" + } + """, ReferentielTypeItem.class)); + + demandeCalcul.setHypotheses(List.of(objectMapper.readValue(""" + [ + { + "code": "CONSO_MOYENNE_VOITURE_ESSENCE", + "valeur": "6.5", + "source": "sourceDefault" + } + ] + """, ReferentielHypothese[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT( + demandeCalcul + ); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertNull(actual.getImpactUnitaire()); + assertEquals("ERREUR", actual.getStatutIndicateur()); + assertEquals(TestJsonUtils.format(""" + { + "erreur": "ErrCalcFonc : Référentiel Facteur Caractérisation inconnu" + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + @Test + void shouldCalculerImpactOperationNonIT_deplacementEssence_utilisation_withoutRefHypotheses_shouldReturnIndicateurWithError() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getEtape().setCode("UTILISATION"); + demandeCalcul.getOperationNonIT().setType("deplacement-voiture-essence"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "deplacement-voiture-essence", + "categorie": "DEPLACEMENT_ESSENCE", + "refHypothese": "CONSO_MOYENNE_VOITURE_ESSENCE", + "refItemParDefaut": "fuel", + "source": "sourceDefault" + } + """, ReferentielTypeItem.class)); + + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "fuel", + "etape": "FABRICATION", + "critere": "Changement Climatique", + "valeur" : 0.1 + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT( + demandeCalcul + ); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertNull(actual.getImpactUnitaire()); + assertEquals("ERREUR", actual.getStatutIndicateur()); + assertEquals(TestJsonUtils.format(""" + { + "erreur": "ErrCalcFonc : Il n'y a pas d'hypothese pour l'item pour la refHypothese 'CONSO_MOYENNE_VOITURE_ESSENCE' de l'item nomItem" + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + @Test + void shouldCalculerImpactOperationNonIT_deplacementHybride_utilisation() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getEtape().setCode("UTILISATION"); + demandeCalcul.getOperationNonIT().setType("deplacement-voiture-hybride"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "deplacement-voiture-hybride", + "categorie": "DEPLACEMENT_HYBRIDE", + "refHypothese": "CONSO_MOYENNE_VOITURE_ESSENCE", + "refItemParDefaut": "fuel", + "source": "sourceDefault" + } + """, ReferentielTypeItem.class)); + + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "fuel", + "etape": "FABRICATION", + "critere": "Changement Climatique", + "valeur" : 0.1 + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + demandeCalcul.setHypotheses(List.of(objectMapper.readValue(""" + [ + { + "code": "CONSO_MOYENNE_VOITURE_ESSENCE", + "valeur": "6.5", + "source": "sourceDefault" + }, + { + "code": "TAUX_VEHICULE_HYBRIDE", + "valeur": "0.85", + "source": "NosGestesClimat.com" + } + ] + """, ReferentielHypothese[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertEquals("OK", actual.getStatutIndicateur()); + assertEquals(0.5525, actual.getImpactUnitaire(), 0.0001d); + assertEquals(TestJsonUtils.format(""" + { + "formule" : "ImpactOperationNonIT = (ConsoMoyenne(6.5) * NbKmParcourus(1.0) * ReferentielFacteurCaracterisation(0.1) * TauxHybride(0.85))", + "hypothese" : { + "nom_hypothese" : "CONSO_MOYENNE_VOITURE_ESSENCE", + "source" : "sourceDefault", + "valeur" : 6.5 + }, + "valeurReferentielFacteurCaracterisation" : 0.1 + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + @Test + void shouldCalculerImpactOperationNonIT_deplacementHybride_utilisation_whithoutHypotheseTaux_shouldReturnIndicateurWithError() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getEtape().setCode("UTILISATION"); + demandeCalcul.getOperationNonIT().setType("deplacement-voiture-hybride"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "deplacement-voiture-hybride", + "categorie": "DEPLACEMENT_HYBRIDE", + "refHypothese": "CONSO_MOYENNE_VOITURE_ESSENCE", + "refItemParDefaut": "fuel", + "source": "sourceDefault" + } + """, ReferentielTypeItem.class)); + + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "fuel", + "etape": "FABRICATION", + "critere": "Changement Climatique", + "valeur" : 0.1 + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + demandeCalcul.setHypotheses(List.of(objectMapper.readValue(""" + [ + { + "code": "CONSO_MOYENNE_VOITURE_ESSENCE", + "valeur": "6.5", + "source": "sourceDefault" + } + ] + """, ReferentielHypothese[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertNull(actual.getImpactUnitaire()); + assertEquals("ERREUR", actual.getStatutIndicateur()); + assertEquals(TestJsonUtils.format(""" + { + "erreur": "ErrCalcFonc : Il n'y a pas de taux renseigné pour les véhicules hybrides dans la table des références" + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + @Test + void shouldCalculerImpactOperationNonIT_deplacementElectrique_utilisation() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getEtape().setCode("UTILISATION"); + demandeCalcul.getOperationNonIT().setType("deplacement-trot-elec"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "deplacement-trot-elec", + "categorie": "DEPLACEMENT_ELECTRIQUE", + "refHypothese": "CONSO_MOYENNE_TROTINETTE_ELECTRIQUE", + "source": "sourceDefault" + } + """, ReferentielTypeItem.class)); + + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "Electricty Mix France", + "etape": "FABRICATION", + "categorie": "electricity-mix", + "critere": "Changement Climatique", + "localisation": "France", + "valeur" : 0.1 + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + demandeCalcul.setHypotheses(List.of(objectMapper.readValue(""" + [ + { + "code": "CONSO_MOYENNE_TROTINETTE_ELECTRIQUE", + "valeur": "1.5", + "source": "sourceDefault" + } + ] + """, ReferentielHypothese[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertEquals("OK", actual.getStatutIndicateur()); + assertEquals(0.15000, actual.getImpactUnitaire(), 0.0001d); + assertEquals(TestJsonUtils.format(""" + { + "formule" : "ImpactOperationNonIT = (ConsoMoyenne(1.5) * NbKmParcourus(1.0) * MixElectrique(0.1))", + "mixElectrique" : { + "serveur" : false, + "valeur" : 0.1, + "valeurReferentielMixElectrique" : 0.1 + } + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + @Test + void shouldCalculerImpactOperationNonIT_deplacementElectrique_utilisation_whithoutMixElec_shouldReturnIndicateurWithError() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getEtape().setCode("UTILISATION"); + demandeCalcul.getOperationNonIT().setType("deplacement-trot-elec"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "deplacement-trot-elec", + "categorie": "DEPLACEMENT_ELECTRIQUE", + "refHypothese": "CONSO_MOYENNE_TROTINETTE_ELECTRIQUE", + "source": "sourceDefault" + } + """, ReferentielTypeItem.class)); + + demandeCalcul.setHypotheses(List.of(objectMapper.readValue(""" + [ + { + "code": "CONSO_MOYENNE_TROTINETTE_ELECTRIQUE", + "valeur": "1.5", + "source": "sourceDefault" + } + ] + """, ReferentielHypothese[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertNull(actual.getImpactUnitaire()); + assertEquals("ERREUR", actual.getStatutIndicateur()); + assertEquals(TestJsonUtils.format(""" + { + "erreur" : "ErrCalcFonc : Il n'existe pas de Mix électrique pour cet item non it : critere: Changement Climatique - operation non it: nomItem - Localisation: France" + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + @Test + void shouldCalculerImpactOperationNonIT_deplacementElectrique_utilisation_whithoutRefConso_shouldReturnIndicateurWithError() throws JsonProcessingException { + // Given + DemandeCalculImpactOperationNonIT demandeCalcul = createDemande(); + demandeCalcul.getEtape().setCode("UTILISATION"); + demandeCalcul.getOperationNonIT().setType("deplacement-trot-elec"); + demandeCalcul.setTypeItem(objectMapper.readValue(""" + { + "type": "deplacement-trot-elec", + "categorie": "DEPLACEMENT_ELECTRIQUE", + "refHypothese": "CONSO_MOYENNE_TROTINETTE_ELECTRIQUE", + "source": "sourceDefault" + } + """, ReferentielTypeItem.class)); + + demandeCalcul.setFacteurCaracterisations(List.of(objectMapper.readValue(""" + [ + { + "nom": "Electricty Mix France", + "etape": "FABRICATION", + "categorie": "electricity-mix", + "critere": "Changement Climatique", + "localisation": "France", + "valeur" : 0.1 + } + ] + """, ReferentielFacteurCaracterisation[].class))); + + // When + var actual = calculImpactOperationNonITService.calculerImpactOperationNonIT(demandeCalcul); + + // Then + assertContentIndicateur(demandeCalcul, actual); + assertNull(actual.getImpactUnitaire()); + assertEquals("ERREUR", actual.getStatutIndicateur()); + assertEquals(TestJsonUtils.format(""" + { + "erreur" : "ErrCalcFonc : Il n'y a pas d'hypothese pour l'item pour la refHypothese 'CONSO_MOYENNE_TROTINETTE_ELECTRIQUE' de l'item nomItem" + } + """), + TestJsonUtils.format(actual.getTrace())); + } + + private void assertContentIndicateur(DemandeCalculImpactOperationNonIT source, ImpactOperationNonIT result) { + assertNotNull(result); + assertEquals(source.getOperationNonIT().getNomItemNonIT(), result.getNomItemNonIT()); + assertEquals(source.getOperationNonIT().getType(), result.getTypeItem()); + assertEquals(source.getOperationNonIT().getQuantite(), result.getQuantite()); + + + assertEquals(source.getOperationNonIT().getNomLot(), result.getNomLot()); + assertEquals(source.getOperationNonIT().getDateLot(), result.getDateLot()); + assertEquals(source.getOperationNonIT().getNomOrganisation(), result.getNomOrganisation()); + assertEquals(source.getOperationNonIT().getNomEntite(), result.getNomEntite()); + + assertEquals(source.getDateCalcul(), result.getDateCalcul()); + + assertEquals(source.getCritere().getNomCritere(), result.getCritere()); + assertEquals(source.getEtape().getCode(), result.getEtapeACV()); + assertEquals(source.getCritere().getUnite(), result.getUnite()); + + assertEquals("1.0", result.getVersionCalcul()); + } +} \ No newline at end of file diff --git a/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactReseauServiceTest.java b/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactReseauServiceTest.java index b20da91b6a9a25f4002b55a72f0a85b3e4a8a339..5ae06bb4b352c4a42b7706847253c733192f4163 100644 --- a/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactReseauServiceTest.java +++ b/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/CalculImpactReseauServiceTest.java @@ -1,9 +1,7 @@ package org.mte.numecoeval.calculs.domain.service; -import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.MockitoAnnotations; import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactReseau; import org.mte.numecoeval.calculs.domain.data.entree.EquipementPhysique; import org.mte.numecoeval.calculs.domain.data.indicateurs.ImpactReseau; @@ -25,12 +23,9 @@ class CalculImpactReseauServiceTest { private CalculImpactReseauService calculImpactService; - ObjectMapper objectMapper = new ObjectMapper(); - @BeforeEach void setUp() { - MockitoAnnotations.openMocks(this); - calculImpactService = new CalculImpactReseauServiceImpl(objectMapper); + calculImpactService = new CalculImpactReseauServiceImpl(); } @Test @@ -45,7 +40,7 @@ class CalculImpactReseauServiceTest { .unite("kg CO_{2} eq") .build(); EquipementPhysique equipementPhysique = EquipementPhysique.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -92,7 +87,7 @@ class CalculImpactReseauServiceTest { .unite("kg CO_{2} eq") .build(); EquipementPhysique equipementPhysique = EquipementPhysique.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -121,7 +116,7 @@ class CalculImpactReseauServiceTest { void shouldReturnError_whenInvalidReference() { //Given EquipementPhysique equipementPhysique = EquipementPhysique.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") @@ -162,13 +157,13 @@ class CalculImpactReseauServiceTest { void shouldReturnError_whenReferenceNotFound() { //Given EquipementPhysique equipementPhysique = EquipementPhysique.builder() - .dateLot(LocalDate.of(2022,1,1)) + .dateLot(LocalDate.of(2022, 1, 1)) .nomOrganisation("Test") .nomLot("Test|20220101") .nomSourceDonnee("Source_Test") .nomEquipementPhysique("Equipement 1") .goTelecharge(4.0f) - .dateLot(LocalDate.of(2023,1,1)) + .dateLot(LocalDate.of(2023, 1, 1)) .build(); ReferentielEtapeACV etapeACV = ReferentielEtapeACV.builder() .code("UTILISATION") diff --git a/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/DureeDeVieEquipementPhysiqueServiceTest.java b/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/DureeDeVieEquipementPhysiqueServiceTest.java index 044d18d58d88bde970c91d3a03baf860b2ba6ca7..60969a2a1d764cb040409b99d68d32816f9c0a9c 100644 --- a/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/DureeDeVieEquipementPhysiqueServiceTest.java +++ b/services/calculs/src/test/java/org/mte/numecoeval/calculs/domain/service/DureeDeVieEquipementPhysiqueServiceTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactEquipementPhysique; +import org.mte.numecoeval.calculs.domain.data.demande.OptionsCalcul; import org.mte.numecoeval.calculs.domain.data.entree.EquipementPhysique; import org.mte.numecoeval.calculs.domain.data.erreur.TypeErreurCalcul; import org.mte.numecoeval.calculs.domain.data.referentiel.ReferentielHypothese; @@ -27,7 +28,7 @@ class DureeDeVieEquipementPhysiqueServiceTest { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/MM/yyyy"); @Test - void whenTypeEquipementDoesntHaveDureeDeVie_shouldUseHypotheseForDureeDeVie()throws Exception{ + void whenTypeEquipementDoesntHaveDureeDeVie_shouldUseHypotheseForDureeDeVie() throws Exception { //Given EquipementPhysique equipementPhysique = EquipementPhysique.builder() @@ -46,21 +47,22 @@ class DureeDeVieEquipementPhysiqueServiceTest { .equipementPhysique(equipementPhysique) .hypotheses(Collections.singletonList(hypothese)) .typeEquipement(typeEquipement) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); //When var actual = dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul); //Then - assertEquals(1.17d,actual.getValeur()); + assertEquals(1.17d, actual.getValeurRetenue()); } @Test - void shouldCalculerDureeVie1d_whenEquipementPhyisqueWithValidDates() throws Exception{ + void shouldCalculerDureeVie1d_whenEquipementPhyisqueWithValidDates() throws Exception { //Given - LocalDate dateAchat = LocalDate.parse("15/08/2020",formatter); - LocalDate dateRetrait = LocalDate.parse("15/06/2021",formatter); + LocalDate dateAchat = LocalDate.parse("15/08/2020", formatter); + LocalDate dateRetrait = LocalDate.parse("15/06/2021", formatter); var equipement = EquipementPhysique.builder() .dateAchat(dateAchat) .dateRetrait(dateRetrait) @@ -69,19 +71,20 @@ class DureeDeVieEquipementPhysiqueServiceTest { .builder() .equipementPhysique(equipement) .typeEquipement(null) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); //When var actual = dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul); //Then - assertEquals(1d,actual.getValeur()); + assertEquals(1d, actual.getValeurRetenue()); } @Test - void shouldCalculerDureeVie365_whenEquipementPhyisqueWithValidDates()throws Exception{ + void shouldCalculerDureeVie365_whenEquipementPhyisqueWithValidDates() throws Exception { //Given - LocalDate dateAchat = LocalDate.parse("15/08/2020",formatter); - LocalDate dateRetrait = LocalDate.parse("15/10/2021",formatter); + LocalDate dateAchat = LocalDate.parse("15/08/2020", formatter); + LocalDate dateRetrait = LocalDate.parse("15/10/2021", formatter); var equipement = EquipementPhysique.builder() .dateAchat(dateAchat) .dateRetrait(dateRetrait) @@ -90,18 +93,19 @@ class DureeDeVieEquipementPhysiqueServiceTest { .builder() .equipementPhysique(equipement) .typeEquipement(null) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); //When var actual = dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul); - var expected = 426d/365d; + var expected = 426d / 365d; //Then - assertEquals(expected,actual.getValeur()); + assertEquals(expected, actual.getValeurRetenue()); } @Test - void taiga864_whenEquipementPhysiqueDateRetraitIsNullShouldUseCurrentDayAsDateRetrait()throws Exception{ + void taiga864_whenEquipementPhysiqueDateRetraitIsNullShouldUseCurrentDayAsDateRetrait() throws Exception { //Given - LocalDate dateAchat = LocalDate.now().minusDays(30); + LocalDate dateAchat = LocalDate.now().minusDays(370); var equipement = EquipementPhysique.builder() .dateAchat(dateAchat) .dateRetrait(null) @@ -110,21 +114,22 @@ class DureeDeVieEquipementPhysiqueServiceTest { .builder() .equipementPhysique(equipement) .typeEquipement(null) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); //When var actual = dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul); - var expected = 30/365d; + var expected = 370 / 365d; //Then - assertEquals(expected,actual.getValeur()); - assertEquals(dateAchat.format(DateTimeFormatter.ISO_DATE),actual.getDateAchat()); - assertEquals(LocalDate.now().format(DateTimeFormatter.ISO_DATE),actual.getDateRetrait()); + assertEquals(expected, actual.getValeurRetenue()); + assertEquals(dateAchat.format(DateTimeFormatter.ISO_DATE), actual.getDateAchat()); + assertEquals(LocalDate.now().format(DateTimeFormatter.ISO_DATE), actual.getDateRetrait()); } @Test - void shouldThrowException_whenInvalideDatesOrder()throws Exception{ + void shouldThrowException_whenInvalideDatesOrder() throws Exception { //Given - LocalDate dateRetrait= LocalDate.parse("15/08/2020",formatter); - LocalDate dateAchat = LocalDate.parse("15/10/2021",formatter); + LocalDate dateRetrait = LocalDate.parse("15/08/2020", formatter); + LocalDate dateAchat = LocalDate.parse("15/10/2021", formatter); var equipement = EquipementPhysique.builder() .dateAchat(dateAchat) .dateRetrait(dateRetrait) @@ -133,12 +138,13 @@ class DureeDeVieEquipementPhysiqueServiceTest { .builder() .equipementPhysique(equipement) .typeEquipement(null) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); //When CalculImpactException exception = - //Then + //Then assertThrows(CalculImpactException.class, - ()-> dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul)); + () -> dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul)); assertEquals(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), exception.getErrorType()); String expectedMessage = "La durée de vie de l'équipement n'a pas pu être déterminée"; @@ -147,7 +153,7 @@ class DureeDeVieEquipementPhysiqueServiceTest { } @Test - void shouldReturnDureeVieDefaut_whenMissingDate()throws Exception{ + void shouldReturnDureeVieDefaut_whenMissingDate() throws Exception { //Given var equipement = EquipementPhysique.builder() .type("laptop") @@ -161,16 +167,17 @@ class DureeDeVieEquipementPhysiqueServiceTest { .equipementPhysique(equipement) .hypotheses(Collections.singletonList(hypothese)) .typeEquipement(null) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); //When DureeDeVie actual = dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul); //Then - assertEquals(1.17d,actual.getValeur()); + assertEquals(1.17d, actual.getValeurRetenue()); } @Test - void whenMissingDate_ShouldUseDureeDeVieTypeEquipementInPriority()throws Exception{ + void whenMissingDate_ShouldUseDureeDeVieTypeEquipementInPriority() throws Exception { //Given var equipement = EquipementPhysique.builder() .type("laptop") @@ -188,16 +195,17 @@ class DureeDeVieEquipementPhysiqueServiceTest { .equipementPhysique(equipement) .typeEquipement(typeEquipement) .hypotheses(Collections.singletonList(hypothese)) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); //When DureeDeVie actual = dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul); //Then - assertEquals(3.5d,actual.getValeur()); + assertEquals(3.5d, actual.getValeurRetenue()); } @Test - void whenMissingDureeForTypeAndHypothese_ShouldThrowException()throws Exception{ + void whenMissingDureeForTypeAndHypothese_ShouldThrowException() throws Exception { //Given var equipement = EquipementPhysique.builder() .type("laptop") @@ -215,6 +223,7 @@ class DureeDeVieEquipementPhysiqueServiceTest { .equipementPhysique(equipement) .typeEquipement(typeEquipement) .hypotheses(Collections.singletonList(hypothese)) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); //When CalculImpactException exception = assertThrows(CalculImpactException.class, () -> dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul)); @@ -225,4 +234,199 @@ class DureeDeVieEquipementPhysiqueServiceTest { assertEquals("La durée de vie par défaut de l'équipement n'a pas pu être déterminée", exception.getMessage()); } + //Tests pour CalculerDuree avec methodeDureeUsage = FIXE + @Test + void shouldCalculerDureeVie1an_whenEquipementPhyisqueWithDureeUsageInterneInf1() throws Exception { + //Given + var equipement = EquipementPhysique.builder() + .dureeUsageInterne(0.8) + .build(); + DemandeCalculImpactEquipementPhysique demandeCalcul = DemandeCalculImpactEquipementPhysique + .builder() + .equipementPhysique(equipement) + .typeEquipement(null) + .optionsCalcul(new OptionsCalcul("FIXE")) + .build(); + //When + var actual = dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul); + + //Then + assertEquals(1d, actual.getValeurRetenue()); + } + + @Test + void shouldCalculerDureeVie1an_whenEquipementPhyisqueWithDureeUsageInterneEtAvalEtAmontInf1() throws Exception { + //Given + var equipement = EquipementPhysique.builder() + .dureeUsageInterne(0.1) + .dureeUsageAmont(0.2) + .dureeUsageAval(0.2) + .build(); + DemandeCalculImpactEquipementPhysique demandeCalcul = DemandeCalculImpactEquipementPhysique + .builder() + .equipementPhysique(equipement) + .typeEquipement(null) + .optionsCalcul(new OptionsCalcul("FIXE")) + .build(); + //When + var actual = dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul); + + //Then + assertEquals(0.1, actual.getDureeUsageInterne()); + assertEquals(0.2, actual.getDureeUsageAmont()); + assertEquals(1d, actual.getValeurRetenue()); + } + + @Test + void shouldCalculerDureeVie_whenEquipementPhysiqueWithDureeUsageInterneSup1() throws Exception { + //Given + var equipement = EquipementPhysique.builder() + .dureeUsageInterne(3.0) + .build(); + DemandeCalculImpactEquipementPhysique demandeCalcul = DemandeCalculImpactEquipementPhysique + .builder() + .equipementPhysique(equipement) + .optionsCalcul(new OptionsCalcul("FIXE")) + .build(); + + //When + var actual = dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul); + + //Then + assertEquals(3.0, actual.getValeurRetenue()); + } + + @Test + void shouldCalculerDureeVie_whenEquipementPhysiqueWithDureeUsageInterne_dureeUsageAmontAndAval() throws Exception { + //Given + var equipement = EquipementPhysique.builder() + .dureeUsageInterne(3.0) + .dureeUsageAmont(2.0) + .dureeUsageAval(1.0) + .build(); + DemandeCalculImpactEquipementPhysique demandeCalcul = DemandeCalculImpactEquipementPhysique + .builder() + .equipementPhysique(equipement) + .optionsCalcul(new OptionsCalcul("FIXE")) + .build(); + + //When + var actual = dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul); + + //Then + assertEquals(6.0, actual.getValeurRetenue()); + } + + @Test + void shouldReturnError_whenEquipementPhysiqueWithDureeUsageInterneNegative() throws Exception { + //Given + var equipement = EquipementPhysique.builder() + .dureeUsageInterne(-1.5) + .build(); + + DemandeCalculImpactEquipementPhysique demandeCalcul = DemandeCalculImpactEquipementPhysique + .builder() + .equipementPhysique(equipement) + .optionsCalcul(new OptionsCalcul("FIXE")) + .build(); + + //When + CalculImpactException exception = assertThrows(CalculImpactException.class, () -> dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul)); + + //Then + assertNotNull(exception, "Une exception doit être levée"); + assertEquals(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), exception.getErrorType()); + assertEquals("La durée d'usage interne ne peut pas être négative ou nulle", exception.getMessage()); + } + + @Test + void shouldCalculerDureeVie1d_whenEquipementPhyisqueWithDureeUsageZero() throws Exception { + //Given + var equipement = EquipementPhysique.builder() + .dureeUsageInterne(0.0) + .build(); + DemandeCalculImpactEquipementPhysique demandeCalcul = DemandeCalculImpactEquipementPhysique + .builder() + .equipementPhysique(equipement) + .typeEquipement(null) + .optionsCalcul(new OptionsCalcul("FIXE")) + .build(); + + //When + CalculImpactException exception = assertThrows(CalculImpactException.class, () -> dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul)); + + //Then + assertNotNull(exception, "Une exception doit être levée"); + assertEquals(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), exception.getErrorType()); + assertEquals("La durée d'usage interne ne peut pas être négative ou nulle", exception.getMessage()); + } + + @Test + void shouldReturnError_whenEquipementPhysiqueWithDureeUsageInterne_dureeUsageAmontNegative() throws Exception { + //Given + var equipement = EquipementPhysique.builder() + .dureeUsageInterne(3.0) + .dureeUsageAmont(-1.0) + .dureeUsageAval(-2.0) + .build(); + + DemandeCalculImpactEquipementPhysique demandeCalcul = DemandeCalculImpactEquipementPhysique + .builder() + .equipementPhysique(equipement) + .optionsCalcul(new OptionsCalcul("FIXE")) + .build(); + + //When + CalculImpactException exception = assertThrows(CalculImpactException.class, () -> dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul)); + + //Then + assertNotNull(exception, "Une exception doit être levée"); + assertEquals(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), exception.getErrorType()); + assertEquals("La durée d'usage amont ne peut pas être négative", exception.getMessage()); + } + + @Test + void shouldReturnError_whenEquipementPhysiqueWithDureeUsageInterne_dureeUsageAmontZero() throws Exception { + //Given + var equipement = EquipementPhysique.builder() + .dureeUsageInterne(3.0) + .dureeUsageAmont(0.0) + .dureeUsageAval(1.0) + .build(); + + DemandeCalculImpactEquipementPhysique demandeCalcul = DemandeCalculImpactEquipementPhysique + .builder() + .equipementPhysique(equipement) + .optionsCalcul(new OptionsCalcul("FIXE")) + .build(); + + //When + var actual = dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul); + + //Then + assertEquals(4.0, actual.getValeurRetenue()); + } + + @Test + void shouldReturnError_whenEquipementPhysiqueWithDureeUsageAvalNegative() throws Exception { + //Given + var equipement = EquipementPhysique.builder() + .dureeUsageInterne(1.0) + .dureeUsageAval(-3.4) + .build(); + + DemandeCalculImpactEquipementPhysique demandeCalcul = DemandeCalculImpactEquipementPhysique + .builder() + .equipementPhysique(equipement) + .optionsCalcul(new OptionsCalcul("FIXE")) + .build(); + + //When + CalculImpactException exception = assertThrows(CalculImpactException.class, () -> dureeDeVieEquipementPhysiqueService.calculerDureeVie(demandeCalcul)); + + //Then + assertNotNull(exception, "Une exception doit être levée"); + assertEquals(TypeErreurCalcul.ERREUR_FONCTIONNELLE.getCode(), exception.getErrorType()); + assertEquals("La durée d'usage aval ne peut pas être négative", exception.getMessage()); + } } \ No newline at end of file diff --git a/services/calculs/src/test/java/org/mte/numecoeval/calculs/steps/CalculImpactEquipementVirtuelStepDefinitions.java b/services/calculs/src/test/java/org/mte/numecoeval/calculs/steps/CalculImpactEquipementVirtuelStepDefinitions.java index fb172819f5c5d2bd15810f9bbde0b8583df10607..7cc4872c731bb0e968382bec43f21ea365005a98 100644 --- a/services/calculs/src/test/java/org/mte/numecoeval/calculs/steps/CalculImpactEquipementVirtuelStepDefinitions.java +++ b/services/calculs/src/test/java/org/mte/numecoeval/calculs/steps/CalculImpactEquipementVirtuelStepDefinitions.java @@ -1,6 +1,5 @@ package org.mte.numecoeval.calculs.steps; -import com.fasterxml.jackson.databind.ObjectMapper; import io.cucumber.datatable.DataTable; import io.cucumber.java.fr.Alors; import io.cucumber.java.fr.Soit; @@ -16,7 +15,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; public class CalculImpactEquipementVirtuelStepDefinitions { DemandeCalculImpactEquipementVirtuel demandeCalculCourante; - + @Soit("Une demande de calcul pour un équipement virtuel tel que") public void initDemandeCalculEquipementVirtuel(DemandeCalculImpactEquipementVirtuel demande) { demandeCalculCourante = demande; @@ -24,7 +23,7 @@ public class CalculImpactEquipementVirtuelStepDefinitions { @Alors("l'impact d'équipement virtuel résultant est tel que") public void checkImpactEquipementVirtuel(DataTable dataTable) { - CalculImpactEquipementVirtuelService service = new CalculImpactEquipementVirtuelServiceImpl(new ObjectMapper()); + CalculImpactEquipementVirtuelService service = new CalculImpactEquipementVirtuelServiceImpl(); var result = assertDoesNotThrow(() -> service.calculerImpactEquipementVirtuel(demandeCalculCourante)); assertNotNull(result); diff --git a/services/calculs/src/test/java/org/mte/numecoeval/calculs/steps/DataTableTypeDefinitions.java b/services/calculs/src/test/java/org/mte/numecoeval/calculs/steps/DataTableTypeDefinitions.java index cf75dd9badb31f3241a4b3c62ada24a128a47cbf..f69aaf98ece7e8df602681e8947e377c41dbaba9 100644 --- a/services/calculs/src/test/java/org/mte/numecoeval/calculs/steps/DataTableTypeDefinitions.java +++ b/services/calculs/src/test/java/org/mte/numecoeval/calculs/steps/DataTableTypeDefinitions.java @@ -6,6 +6,7 @@ import org.apache.commons.lang3.StringUtils; import org.mte.numecoeval.calculs.CucumberIntegrationTest; import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactEquipementPhysique; import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactEquipementVirtuel; +import org.mte.numecoeval.calculs.domain.data.demande.OptionsCalcul; import org.mte.numecoeval.calculs.domain.data.entree.EquipementPhysique; import org.mte.numecoeval.calculs.domain.data.entree.EquipementVirtuel; import org.mte.numecoeval.calculs.domain.data.indicateurs.ImpactEquipementPhysique; @@ -27,29 +28,31 @@ public class DataTableTypeDefinitions { public static void assertDateIfAvailable(LocalDate valueToTest, Map<String, String> entry, String key) { assertEquals(getDateOrNull(entry, key), valueToTest); } + public static void assertDoubleIfAvailable(Double valueToTest, Map<String, String> entry, String key) { assertEquals(getDoubleOrNull(entry, key), valueToTest); } + public static void assertIntegerIfAvailable(Integer valueToTest, Map<String, String> entry, String key) { assertEquals(getIntegerOrNull(entry, key), valueToTest); } + public static void assertStringIfAvailable(String valueToTest, Map<String, String> entry, String key) { assertEquals(entry.getOrDefault(key, null), valueToTest); } private static LocalDate getDateOrNull(Map<String, String> entry, String key) { - if( StringUtils.isNotBlank(entry.get(key)) ) { + if (StringUtils.isNotBlank(entry.get(key))) { return LocalDate.parse(entry.get(key), CucumberIntegrationTest.FORMATTER_FRENCH_FORMAT); } return null; } private static Double getDoubleOrNull(Map<String, String> entry, String key) { - if( StringUtils.isNotBlank(entry.get(key)) ) { + if (StringUtils.isNotBlank(entry.get(key))) { try { return NUMBER_FRENCH_FORMAT.parse(entry.get(key)).doubleValue(); - } - catch (ParseException e) { + } catch (ParseException e) { log.error("Erreur au parsing de la valeur {} : {}", entry.get(key), e.getMessage()); return null; } @@ -58,11 +61,10 @@ public class DataTableTypeDefinitions { } private static Integer getIntegerOrNull(Map<String, String> entry, String key) { - if( StringUtils.isNotBlank(entry.get(key)) ) { + if (StringUtils.isNotBlank(entry.get(key))) { try { return NUMBER_FRENCH_FORMAT.parse(entry.get(key)).intValue(); - } - catch (ParseException e) { + } catch (ParseException e) { log.error("Erreur au parsing de la valeur {} : {}", entry.get(key), e.getMessage()); return null; } @@ -74,6 +76,7 @@ public class DataTableTypeDefinitions { public DemandeCalculImpactEquipementPhysique demandeCalculImpactEquipementPhysique(Map<String, String> entry) { var builder = DemandeCalculImpactEquipementPhysique.builder() .dateCalcul(LocalDateTime.now()) + .optionsCalcul(new OptionsCalcul("REEL")) .equipementPhysique( EquipementPhysique.builder() .nomEquipementPhysique(entry.getOrDefault("nomEquipementPhysique", null)) @@ -83,7 +86,7 @@ public class DataTableTypeDefinitions { ); var hypotheses = new ArrayList<ReferentielHypothese>(); - if(StringUtils.isNotBlank(entry.get("refTypeEquipement.dureeVieDefaut"))) { + if (StringUtils.isNotBlank(entry.get("refTypeEquipement.dureeVieDefaut"))) { builder.typeEquipement( ReferentielTypeEquipement.builder() .dureeVieDefaut(getDoubleOrNull(entry, "refTypeEquipement.dureeVieDefaut")) @@ -91,7 +94,7 @@ public class DataTableTypeDefinitions { ); } - if(StringUtils.isNotBlank(entry.get("hypothese.dureeVieParDefaut"))) { + if (StringUtils.isNotBlank(entry.get("hypothese.dureeVieParDefaut"))) { hypotheses.add( ReferentielHypothese.builder() .code("dureeVieParDefaut") @@ -139,10 +142,10 @@ public class DataTableTypeDefinitions { impactEquipement.setNomOrganisation(entry.getOrDefault("impactEquipementPhysique.nomOrganisation", null)); impactEquipement.setDateLot(getDateOrNull(entry, "impactEquipementPhysique.dateLot")); impactEquipement.setNomEntite(entry.getOrDefault("impactEquipementPhysique.nomEntite", null)); - if(StringUtils.isNotBlank(entry.get("impactEquipementPhysique.impactUnitaire"))) { + if (StringUtils.isNotBlank(entry.get("impactEquipementPhysique.impactUnitaire"))) { impactEquipement.setImpactUnitaire(getDoubleOrNull(entry, "impactEquipementPhysique.impactUnitaire")); } - if(StringUtils.isNotBlank(entry.get("impactEquipementPhysique.consoElecMoyenne"))) { + if (StringUtils.isNotBlank(entry.get("impactEquipementPhysique.consoElecMoyenne"))) { impactEquipement.setConsoElecMoyenne(getDoubleOrNull(entry, "impactEquipementPhysique.consoElecMoyenne")); } builder.impactEquipement(impactEquipement); diff --git a/services/calculs/src/test/java/org/mte/numecoeval/calculs/steps/DureeDeVieStepDefinitions.java b/services/calculs/src/test/java/org/mte/numecoeval/calculs/steps/DureeDeVieStepDefinitions.java index abeee6a6a1e7d17f3515c1235449c8fc3e936929..6fa5c36838d58114378fdf8ec71a2062889b0ea6 100644 --- a/services/calculs/src/test/java/org/mte/numecoeval/calculs/steps/DureeDeVieStepDefinitions.java +++ b/services/calculs/src/test/java/org/mte/numecoeval/calculs/steps/DureeDeVieStepDefinitions.java @@ -3,6 +3,7 @@ package org.mte.numecoeval.calculs.steps; import io.cucumber.java.fr.Alors; import io.cucumber.java.fr.Soit; import org.mte.numecoeval.calculs.domain.data.demande.DemandeCalculImpactEquipementPhysique; +import org.mte.numecoeval.calculs.domain.data.demande.OptionsCalcul; import org.mte.numecoeval.calculs.domain.data.entree.EquipementPhysique; import org.mte.numecoeval.calculs.domain.data.trace.DureeDeVie; import org.mte.numecoeval.calculs.domain.exception.CalculImpactException; @@ -31,6 +32,7 @@ public class DureeDeVieStepDefinitions { .dateRetrait(LocalDate.parse(dateRetrait, FORMATTER_FRENCH_FORMAT)) .build() ) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); } @@ -45,6 +47,7 @@ public class DureeDeVieStepDefinitions { .dateRetrait(null) .build() ) + .optionsCalcul(new OptionsCalcul("REEL")) .build(); } @@ -55,7 +58,7 @@ public class DureeDeVieStepDefinitions { DureeDeVie result = assertDoesNotThrow(() -> service.calculerDureeVie(demandeCalculCourante)); assertNotNull(result); - assertEquals(dureeDeVieAttendue, result.getValeur()); + assertEquals(dureeDeVieAttendue, result.getValeurRetenue()); } @Alors("la durée de vie correspond à la différence entre la date d'achat et la date du jour") @@ -66,7 +69,7 @@ public class DureeDeVieStepDefinitions { assertNotNull(result); double differenceAvecDateDuJour = ChronoUnit.DAYS.between(demandeCalculCourante.getEquipementPhysique().getDateAchat(), LocalDate.now()) / 365d; - assertEquals(differenceAvecDateDuJour, result.getValeur()); + assertEquals(differenceAvecDateDuJour, result.getValeurRetenue()); } @Soit("Une demande de calcule de durée de vie tel que") diff --git a/services/common/pom.xml b/services/common/pom.xml index a218572f6f118181b85c5bf24bd02f338791232c..2b6529ac907ecfd333a3d7c34dfb3167a79d0a33 100644 --- a/services/common/pom.xml +++ b/services/common/pom.xml @@ -5,12 +5,12 @@ <parent> <groupId>org.mte.numecoeval</groupId> <artifactId>core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <artifactId>common</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> <name>common</name> <description>Module commun</description> diff --git a/services/common/src/main/resources/static/api-event-calculs-async-openapi.yaml b/services/common/src/main/resources/static/api-event-calculs-async-openapi.yaml index 2d849a925c872dd0f334a5e254848b81868a0379..a010005d45e6ff2ecc240b65cdc726aa1e1d132f 100644 --- a/services/common/src/main/resources/static/api-event-calculs-async-openapi.yaml +++ b/services/common/src/main/resources/static/api-event-calculs-async-openapi.yaml @@ -13,6 +13,8 @@ tags: description: Endpoints liés aux calculs pour un équipement virtuel - name: Calculs Application description: Endpoints liés aux calculs pour une application + - name: Calculs OperationNonIT + description: Endpoints liés aux calculs pour une opération non IT - name: Calculs Messagerie description: Endpoints liés aux calculs pour un élément de messagerie - name: Calculs Reseau @@ -152,6 +154,39 @@ paths: 'application/json': schema: $ref: "#/components/schemas/IndicateurImpactApplicationRest" + /calculs/operationNonIT: + post: + summary: Endpoint pour le calcul unitaire d'impact écologique pour une opération Non IT. + description: | + Endpoint pour le calcul unitaire d'impact écologique pour une opération Non IT. + tags: + - Calculs OperationNonIT + operationId: calculerImpactOperationNonIT + requestBody: + required: true + content: + 'application/json': + schema: + $ref: "#/components/schemas/DemandeCalculImpactOperationNonITRest" + responses: + "500": + description: Erreur interne du service + content: + 'application/json': + schema: + $ref: "#/components/schemas/ErreurRest" + "400": + description: Indicateur en erreur + content: + 'application/json': + schema: + $ref: "#/components/schemas/IndicateurImpactOperationNonITRest" + "200": + description: Indicateur calculé. + content: + 'application/json': + schema: + $ref: "#/components/schemas/IndicateurImpactOperationNonITRest" /calculs/messagerie: post: summary: Endpoint pour le calcul unitaire d'impact écologique pour un élément de messagerie. @@ -235,6 +270,18 @@ components: description: "" type: string format: date + dureeUsageInterne: + description: "" + type: number + format: double + dureeUsageAmont: + description: "" + type: number + format: double + dureeUsageAval: + description: "" + type: number + format: double nbCoeur: description: "" type: string @@ -261,6 +308,9 @@ components: type: number format: double default: 1.0 + qualite: + description: "Qualité de la donnée" + type: string consoElecAnnuelle: description: "" type: number @@ -289,6 +339,9 @@ components: localisation: description: "" type: string + qualite: + description: "Qualité de la donnée" + type: string EquipementVirtuelRest: description: Représentation d'un équipement virtuel dans NumEcoEval properties: @@ -324,6 +377,9 @@ components: Consommation électrique annuelle de l'équipement virtuel. type: number format: double + qualite: + description: "Qualité de la donnée" + type: string ApplicationRest: description: Représentation d'une application dans NumEcoEval properties: @@ -345,6 +401,48 @@ components: sousDomaine: description: "" type: string + qualite: + description: "Qualité de la donnée" + type: string + OperationNonITRest: + description: Représentation d'opérations non IT dans NumEcoEval + properties: + nomItemNonIT: + description: "" + type: string + quantite: + description: "" + type: number + format: double + type: + description: "" + type: string + dureeDeVie: + description: "" + type: number + format: double + localisation: + description: "" + type: string + nomEntite: + description: "" + type: string + nomSourceDonnee: + description: "Nom de la source de la donnée" + type: string + nomCourtDatacenter: + description: "" + type: string + description: + description: "" + type: string + consoElecAnnuelle: + description: "" + type: number + format: double + qualite: + description: "Qualité de la donnée" + type: string MessagerieRest: description: Représentation d'éléments de messagerie dans NumEcoEval properties: @@ -393,6 +491,27 @@ components: refEquipementParDefaut: type: string description: Référentiel de type d'équipement physique. + TypeItemRest: + type: object + properties: + type: + type: string + categorie: + type: string + serveur: + type: boolean + commentaire: + type: string + dureeVieDefaut: + type: number + format: double + refCosoMoyenne: + type: string + source: + type: string + refItemParDefaut: + type: string + description: Référentiel des types d'item. HypotheseRest: type: object properties: @@ -467,6 +586,36 @@ components: type: number format: double description: Référentiel d'impact écologique pour un équipement physique + FacteurCaracterisationRest: + type: object + description: Référentiel des facteurs de caractérisation pour un item + properties: + nom: + type: string + etape: + type: string + critere: + type: string + niveau: + type: string + tiers: + type: string + categorie: + type: string + source: + type: string + valeur: + type: number + format: double + unite: + type: string + consoElecMoyenne: + type: number + format: double + localisation: + type: string + description: + type: string ImpactMessagerieRest: type: object description: Référentiel - L'équation d'impact est une fonction affine de la forme a * x + b @@ -527,6 +676,9 @@ components: format: int32 statutEquipementPhysique: type: string + qualite: + description: "Qualité de la donnée" + type: string IndicateurImpactReseauRest: type: object properties: @@ -558,6 +710,9 @@ components: impactUnitaire: type: number format: double + qualite: + description: "Qualité de la donnée" + type: string IndicateurImpactEquipementVirtuelRest: description: Indicateur d'impact écologique d'un équipement virtuel type: object @@ -601,6 +756,9 @@ components: consoElecMoyenne: type: number format: double + qualite: + description: "Qualité de la donnée" + type: string IndicateurImpactApplicationRest: description: Impact d'application properties: @@ -649,6 +807,55 @@ components: consoElecMoyenne: type: number format: double + qualite: + description: "Qualité de la donnée" + type: string + IndicateurImpactOperationNonITRest: + type: object + properties: + dateCalcul: + type: string + description: "Date et Heure du calcul, même valeur pour tous les indicateurs\ + \ créés avec le même lot d'objets d'entrées" + format: date-time + versionCalcul: + type: string + etapeACV: + type: string + description: "Code de l'étape ACV associé à l'indicateur, peut être null\ + \ pour certains indicateurs" + critere: + type: string + description: "Nom du critère associé à l'indicateur, peut être null pour\ + \ certains indicateurs" + statutIndicateur: + type: string + description: "Statut de l'indicateur, vaut \"OK\" si l'indicateur est calcul\ + \ et \"ERREUR\" si l'indicateur est en erreur" + trace: + type: string + description: Trace du calcul ayant produit l'indicateur + unite: + type: string + description: "Unite du critère associé, peut être null" + nomItemNonIT: + type: string + typeItem: + type: string + impactUnitaire: + type: number + format: double + consoElecMoyenne: + type: number + format: double + quantite: + type: integer + format: int32 + statutItem: + type: string + qualite: + description: "Qualité de la donnée" + type: string IndicateurImpactMessagerieRest: description: Indicateur d'impact de messagerie properties: @@ -775,6 +982,27 @@ components: type: integer impactEquipementVirtuel: $ref: "#/components/schemas/IndicateurImpactEquipementVirtuelRest" + DemandeCalculImpactOperationNonITRest: + description: Objet regroupant toutes les données pour le calcul des indicateurs d'impact des opérations non it dans NumEcoEval + type: object + properties: + operationNonIT: + $ref: "#/components/schemas/OperationNonITRest" + typeItem: + $ref: "#/components/schemas/TypeItemRest" + hypotheses: + type: array + items: + $ref: "#/components/schemas/HypotheseRest" + etape: + $ref: "#/components/schemas/EtapeRest" + critere: + $ref: "#/components/schemas/CritereRest" + facteurCaracterisations: + description: Facteur de caractérisation de l'item + type: array + items: + $ref: "#/components/schemas/FacteurCaracterisationRest" DemandeCalculMessagerieRest: description: Objet regroupant toutes les données pour le calcul des indicateurs d'impact de messagerie dans NumEcoEval type: object diff --git a/services/common/src/main/resources/static/api-event-calculs-openapi.yaml b/services/common/src/main/resources/static/api-event-calculs-openapi.yaml index 05125bcc30281d7396000431e4eb1b45f324b9b9..b066c967a066392ce1acbdd531ebf3e72e96a33f 100644 --- a/services/common/src/main/resources/static/api-event-calculs-openapi.yaml +++ b/services/common/src/main/resources/static/api-event-calculs-openapi.yaml @@ -264,6 +264,9 @@ components: nbTotalVCPU: description: "Nombre total de VCPU (correspond à la somme des vCPU définis dans les équipements virtuels) ou null si un des équipements virtuels n'a pas de vCPU - Utilisé dans les traitements" type: integer + qualite: + description: "Qualité de la donnée" + type: string dataCenter: $ref: "#/components/schemas/DataCenterRest" DataCenterRest: @@ -282,6 +285,9 @@ components: localisation: description: "" type: string + qualite: + description: "Qualité de la donnée" + type: string EquipementVirtuelRest: description: Représentation d'un équipement virtuel dans NumEcoEval properties: @@ -317,6 +323,9 @@ components: Consommation électrique annuelle de l'équipement virtuel. type: number format: double + qualite: + description: "Qualité de la donnée" + type: string ApplicationRest: description: Représentation d'une application dans NumEcoEval properties: @@ -338,6 +347,9 @@ components: sousDomaine: description: "" type: string + qualite: + description: "Qualité de la donnée" + type: string MessagerieRest: description: Représentation d'éléments de messagerie dans NumEcoEval properties: @@ -520,6 +532,9 @@ components: format: int32 statutEquipementPhysique: type: string + qualite: + description: "Qualité de la donnée" + type: string IndicateurImpactReseauRest: type: object properties: @@ -551,6 +566,9 @@ components: impactUnitaire: type: number format: double + qualite: + description: "Qualité de la donnée" + type: string IndicateurImpactEquipementVirtuelRest: description: Indicateur d'impact écologique d'un équipement virtuel type: object @@ -594,6 +612,9 @@ components: consoElecMoyenne: type: number format: double + qualite: + description: "Qualité de la donnée" + type: string IndicateurImpactApplicationRest: description: Impact d'application properties: @@ -642,6 +663,9 @@ components: consoElecMoyenne: type: number format: double + qualite: + description: "Qualité de la donnée" + type: string IndicateurImpactMessagerieRest: description: Indicateur d'impact de messagerie properties: diff --git a/services/common/src/main/resources/static/api-event-calculs-sync-openapi.yaml b/services/common/src/main/resources/static/api-event-calculs-sync-openapi.yaml index fc99e3ad7b1bc92c41175d0d6c21fd576af7237c..f91664302e28929444f4589cc729456a4346e6e4 100644 --- a/services/common/src/main/resources/static/api-event-calculs-sync-openapi.yaml +++ b/services/common/src/main/resources/static/api-event-calculs-sync-openapi.yaml @@ -9,11 +9,11 @@ info: paths: /sync/calculs: post: - summary: Endpoint pour le calcul unitaire d'impact écologique synchrone pour une liste d'id d'équipements physiques et de messageries. + summary: Endpoint pour le calcul unitaire d'impact écologique synchrone pour une liste d'id d'équipements physiques, d'opérations non IT et de messageries. description: | - Endpoint pour le calcul unitaire d'impact écologique pour un équipement physique. + Endpoint pour le calcul unitaire d'impact écologique pour un équipement physique, une opération non IT et une messagerie. tags: - - Calculs Equipement Physique et Messagerie + - Calculs Equipement Physique et Operation non IT et Messagerie operationId: syncCalculByIds requestBody: required: true @@ -55,7 +55,7 @@ components: format: date-time # Entrées SyncCalculRest: - description: Représentation d'un équipement physique dans NumEcoEval + description: Représentation d'un équipement physique, d'une opération non IT et d'une messagerie dans NumEcoEval type: object properties: equipementPhysiqueIds: @@ -64,6 +64,12 @@ components: items: type: integer format: int64 + operationNonITIds: + description: "" + type: array + items: + type: integer + format: int64 messagerieIds: description: "" type: array @@ -85,8 +91,12 @@ components: nbrApplication: type: integer format: int64 - description: "Nombre total d'applications traités" + description: "Nombre total d'applications traitées" + nbrOperationNonIT: + type: integer + format: int64 + description: "Nombre total d'opérations non IT traitées" nbrMessagerie: type: integer format: int64 - description: "Nombre total de messageries traités" + description: "Nombre total de messageries traitées" diff --git a/services/common/src/main/resources/static/api-referentiels-openapi.yaml b/services/common/src/main/resources/static/api-referentiels-openapi.yaml index d6e764c017f0a83ce97f2515f85222f9281eab4a..9a754523437ec3bbb716886b1a673e2104e081d5 100644 --- a/services/common/src/main/resources/static/api-referentiels-openapi.yaml +++ b/services/common/src/main/resources/static/api-referentiels-openapi.yaml @@ -20,6 +20,86 @@ externalDocs: description: NumEcoEval Documentation url: https://gitlab-forge.din.developpement-durable.gouv.fr/pub/numeco/m4g/docs paths: + /referentiel/typeItem/csv: + get: + tags: + - Export Référentiels + summary: Exporter les impacts des types d'items sous format csv + description: | + <ul> + <li>Entrée : Aucune </li> + <li>Sortie : Renvoie la liste des étapes de ref_TypeItem </li> + </ul> + operationId: exportTypeItemCSV + responses: + '200': + description: OK + '400': + description: Bad Request + content: + application/hal+json: + schema: + $ref: '#/components/schemas/ErrorResponseDTO' + '404': + description: Not Found + content: + application/hal+json: + schema: + $ref: '#/components/schemas/ErrorResponseDTO' + '500': + description: Internal Server Error + content: + application/hal+json: + schema: + $ref: '#/components/schemas/ErrorResponseDTO' + post: + tags: + - Import Référentiels + summary: 'Alimentation du référentiel Type Item par csv : annule et remplace.' + description: | + Le référentiel est global à tout le système. L’import se fait uniquement avec un fichier CSV. + Lors de l’import, les données précédentes sont supprimées. + <ul> + <li>Entrée : Le fichier CSV du référentiel</li> + <li>Sortie : Rapport du fichier CSV (nombre de lignes totales, nombre de lignes en erreur, nombre de lignes traitées, liste des erreurs par lignes).</li> + </ul> + operationId: importTypeItemCSV + requestBody: + content: + multipart/form-data: + schema: + required: + - file + type: object + properties: + file: + type: string + format: binary + responses: + '200': + description: Rapport d'import du fichier CSV + content: + application/hal+json: + schema: + $ref: '#/components/schemas/RapportImportDTO' + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponseDTO' + '404': + description: Not Found + content: + application/hal+json: + schema: + $ref: '#/components/schemas/ErrorResponseDTO' + '500': + description: Internal Server Error + content: + application/hal+json: + schema: + $ref: '#/components/schemas/ErrorResponseDTO' /referentiel/typeEquipement/csv: get: tags: @@ -862,6 +942,86 @@ paths: application/hal+json: schema: $ref: '#/components/schemas/ErrorResponseDTO' + /referentiel/typesItem: + get: + tags: + - Interne NumEcoEval + summary: Endpoint interne à NumEcoEval - Récupération de tous les types d'items + description: | + Endpoint interne utilisé à la réception de données d'entrées par le module api-expositiondonneesentrees de NumEcoEval. + Renvoie l'intégralité des types d'items utilisables par NumEcoEval. + + Les types d'items servent notamment à alimenter la durée de vie par défaut des items + reçues. + operationId: getAllTypeItem + responses: + '200': + description: Types Item + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/TypeItemDTO' + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponseDTO' + '404': + description: Types Item non trouvé + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponseDTO' + '500': + description: Internal Server Error + content: + application/hal+json: + schema: + $ref: '#/components/schemas/ErrorResponseDTO' + /referentiel/typesItem/{type}: + get: + tags: + - Interne NumEcoEval + summary: Endpoint interne à NumEcoEval - Récupération d'items via leur type + description: | + Endpoint interne utilisé à la réception de données d'entrées par le module api-expositiondonneesentrees de NumEcoEval. Renvoie l'intégralité des types d'items d'un certain type. + operationId: getTypeItem + parameters: + - name: type + in: path + description: type recherché + required: true + schema: + type: string + description: type recherché + responses: + '200': + description: Types Item + content: + application/json: + schema: + $ref: '#/components/schemas/TypeItemDTO' + '400': + description: Invalid request + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponseDTO' + '404': + description: Types Item non trouvé + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponseDTO' + '500': + description: Internal Server Error + content: + application/hal+json: + schema: + $ref: '#/components/schemas/ErrorResponseDTO' /referentiel/typesEquipement: get: tags: @@ -1292,46 +1452,64 @@ paths: get: tags: - Interne NumEcoEval - summary: Endpoint interne à NumEcoEval - Récupération d'un Facteur de Caractérisation + summary: Endpoint interne à NumEcoEval - Récupération des Facteurs de Caractérisation description: | Endpoint interne utilisé dans la génération des indicateurs par le module api-calcul de NumEcoEval. - Récupération d'un impact équipement en fonction de 3 paramètres: + Récupération des Facteurs de Caractérisation en fonction de 5 paramètres: <ul> - <li>Le nom du facteur de caractérisation: nom</li> - <li>L'étape ACV: etape</li> - <li>Le critère d'impact: critere</li> + <li>Le nom du critère d'impact écologique: critere</li> + <li>Le code de l'étape ACV: etapeacv</li> + <li>Le nom du facteur de caractérisation recherché: nom</li> + <li>La localisation: localisation</li> + <li>La catégorie: categorie</li> </ul> . operationId: getFacteurCaracterisation parameters: - - name: nom - in: query - description: Nom du facteur de caractérisation recherché - required: true - schema: - type: string - description: Nom du facteur de caractérisation recherché - name: critere in: query description: Nom du critère d'impact écologique - required: true + required: false schema: type: string description: Nom du critère d'impact écologique - name: etapeacv in: query description: Code de l'étape ACV - required: true + required: false schema: type: string description: Code de l'étape ACV + - name: nom + in: query + description: Nom du facteur de caractérisation recherché + required: false + schema: + type: string + description: Nom du facteur de caractérisation recherché + - name: localisation + in: query + description: Nom de la localisation + required: false + schema: + type: string + description: Nom de la localisation + - name: categorie + in: query + description: Nom de la catégorie + required: false + schema: + type: string + description: Nom de la catégorie responses: '200': - description: Facteur Caractérisation trouvé + description: Liste des Facteurs de Caractérisation trouvés content: application/json: schema: - $ref: '#/components/schemas/FacteurCaracterisationDTO' + type: array + items: + $ref: '#/components/schemas/FacteurCaracterisationDTO' '400': description: Invalid request content: @@ -1567,6 +1745,35 @@ components: type: string description: La version description: Version applicative + TypeItemDTO: + type: object + properties: + type: + type: string + description: Type d'item, clé du référentiel + categorie: + type: string + description: Catégorie de l'item + serveur: + type: boolean + description: Flag indiquant si l'item est un serveur + commentaire: + type: string + description: Commentaire de l'entrée dans le référentiel + dureeVieDefaut: + type: number + description: Durée de vie par défaut de ce type d'item + format: double + refHypothese: + type: string + description: Référence vers l'hypothèse nécessaire pour le calcul d'impact de cet item + source: + type: string + description: Source de l'information du référentiel + refItemParDefaut: + type: string + description: Référence de l'item par défaut, permet des correspondances en cas d'absence de correspondance directe + description: Référentiel des types d'items utilisables dans le système. La clé du référentiel est le champ type. TypeEquipementDTO: type: object properties: @@ -1698,6 +1905,9 @@ components: source: type: string description: Source de l'hypothèse + description: + type: string + description: Description de l'hypothèse description: Référentiel des hypothèses utilisées pour les calculs FacteurCaracterisationDTO: type: object diff --git a/services/common/src/main/resources/static/asyncapi_equipement_physique.yaml b/services/common/src/main/resources/static/asyncapi_equipement_physique.yaml index 704d8b3ce986bce1220326578b1380361962a736..bb8585f9453907814c04fc1cfef4f2aa44ed1df8 100644 --- a/services/common/src/main/resources/static/asyncapi_equipement_physique.yaml +++ b/services/common/src/main/resources/static/asyncapi_equipement_physique.yaml @@ -116,6 +116,18 @@ components: description: "" type: string format: date + dureeUsageInterne: + description: "" + type: number + format: double + dureeUsageAmont: + description: "" + type: number + format: double + dureeUsageAval: + description: "" + type: number + format: double nbCoeur: description: "" type: string @@ -154,6 +166,9 @@ components: nomSourceDonnee: description: "Nom de la source de la donnée" type: string + qualite: + description: "Qualité de la donnée" + type: string nomLot: description: "Nom du lot rattaché" type: string @@ -215,6 +230,9 @@ components: nomOrganisation: description: "" type: string + qualite: + description: "Qualité de la donnée" + type: string CorrespondanceRefEquipementDTO: type: object properties: diff --git a/services/common/src/main/resources/static/asyncapi_merge.yaml b/services/common/src/main/resources/static/asyncapi_merge.yaml index b92b45a095c8ac4a977d6e0e92d074a78edccbc9..b8c6c9dad75e007b4f94456613ebbc7d6ddd1181 100644 --- a/services/common/src/main/resources/static/asyncapi_merge.yaml +++ b/services/common/src/main/resources/static/asyncapi_merge.yaml @@ -22,5 +22,9 @@ components: $ref: "./asyncapi_equipement_physique.yaml#/components/schemas/EquipementPhysiqueDTO" DataCenterDTO: $ref: "./asyncapi_equipement_physique.yaml#/components/schemas/DataCenterDTO" + CalculOperationNonITDTO: + $ref: "./asyncapi_operation_non_it.yaml#/components/schemas/CalculOperationNonITDTO" + OperationNonITDTO: + $ref: "./asyncapi_operation_non_it.yaml#/components/schemas/OperationNonITDTO" MessagerieDTO: $ref: "./asyncapi_messagerie.yaml#/components/schemas/MessagerieDTO" diff --git a/services/common/src/main/resources/static/asyncapi_operation_non_it.yaml b/services/common/src/main/resources/static/asyncapi_operation_non_it.yaml new file mode 100644 index 0000000000000000000000000000000000000000..bd130605387eb82d27bcb0fddd40dfb376701178 --- /dev/null +++ b/services/common/src/main/resources/static/asyncapi_operation_non_it.yaml @@ -0,0 +1,211 @@ +asyncapi: 2.6.0 +info: + title: api-event-calcul-enrichissement-opnonit + version: '1.0' + description: | + Lecture d'une opération non it + puis récupération des référentiels nécessaires au calcul via REST + puis production d'un message pour demande de calcul d'impacts de l'opération non IT +servers: + bootstrap: + url: localhost:9092 + protocol: kafka +channels: + entree_operationNonIT: + description: Topic d'envoi des données d'entrées pour les opérations non IT à enrichir + publish: + message: + $ref: '#/components/messages/EntreeOperationNonIT' + calcul_operationNonIT: + description: Topic d'envoi des données d'entrées pour les opérations non IT à calculer + subscribe: + message: + $ref: '#/components/messages/CalculOperationNonIT' +components: + messages: + EntreeOperationNonIT: + name: EntreeOperationNonIT + title: Message des données d'entrée pour une opération non IT dans NumEcoEval + summary: Données d'une opération non it pour un calcul dans NumEcoEval + contentType: application/json + payload: + $ref: "#/components/schemas/OperationNonITDTO" + CalculOperationNonIT: + name: CalculOperationNonIT + title: Message pour le calcul d'impact d'une opération non it + summary: Intégralité des données permettant le calcul d'une opération non it pour un calcul dans NumEcoEval + contentType: application/json + payload: + $ref: "#/components/schemas/CalculOperationNonITDTO" + schemas: + CalculOperationNonITDTO: + $id: CalculOperationNonITDTO + description: Objet regroupant toutes les données pour le calcul des indicateurs d'une opération non it dans NumEcoEval + type: object + properties: + operationNonIT: + $ref: "#/components/schemas/OperationNonITDTO" + typeItem: + description: Référentiel rattaché au type d'item de l'opération non it + $ref: "#/components/schemas/TypeItemDTO" + hypotheses: + description: Hypothèses disponibles pour le calcul + type: array + items: + $ref: "#/components/schemas/HypotheseDTO" + etapes: + description: Référentiels des Étapes ACV + type: array + items: + $ref: "#/components/schemas/EtapeDTO" + criteres: + description: Référentiels des Critères d'impact écologiques + type: array + items: + $ref: "#/components/schemas/CritereDTO" + facteurCaracterisation: + description: Facteur de caracterisation de l'item + type: array + items: + $ref: "#/components/schemas/FacteurCaracterisationDTO" + OperationNonITDTO: + $id: OperationNonITDTO + description: Représentation d'une opération non it dans NumEcoEval + type: object + properties: + id: + description: "" + type: integer + format: int64 + nomItemNonIT: + description: "" + type: string + quantite: + description: "" + type: number + format: double + type: + description: "" + type: string + dureeDeVie: + description: "" + type: number + format: double + localisation: + description: "" + type: string + nomEntite: + description: "" + type: string + nomSourceDonnee: + description: "Nom de la source de la donnée" + type: string + nomCourtDatacenter: + description: "" + type: string + description: + description: "" + type: string + consoElecAnnuelle: + description: "" + type: number + format: double + nomLot: + description: "Nom du lot rattaché" + type: string + dateLot: + description: "" + type: string + format: date + nomOrganisation: + description: "" + type: string + qualite: + description: "Qualité de la donnée" + type: string + TypeItemDTO: + type: object + properties: + type: + type: string + categorie: + type: string + serveur: + type: boolean + commentaire: + type: string + dureeVieDefaut: + type: number + format: double + refCosoMoyenne: + type: string + source: + type: string + refItemParDefaut: + type: string + description: Référentiel des types d'item. + HypotheseDTO: + type: object + properties: + code: + type: string + valeur: + type: string + source: + type: string + description: + type: string + EtapeDTO: + type: object + properties: + code: + type: string + libelle: + type: string + CritereDTO: + type: object + properties: + nomCritere: + type: string + description: Nom du critère d'impact écologique + unite: + type: string + description: Unité du critère d'impact écologique + description: + type: string + description: Description du critère d'impact écologique + FacteurCaracterisationDTO: + type: object + properties: + nom: + type: string + etape: + type: string + critere: + type: string + niveau: + type: string + tiers: + type: string + categorie: + type: string + source: + type: string + valeur: + type: number + format: double + unite: + type: string + consoElecMoyenne: + type: number + format: double + localisation: + type: string + description: + type: string + description: Référentiel des facteurs de caractérisation pour un item + operationTraits: + kafka: + bindings: + kafka: + groupId: api-event-calcul-enrichissement-opnonit diff --git a/services/core/pom.xml b/services/core/pom.xml index 473de7d2929025fa7e222fc5de021d2782bc7b5d..849bde9fd955765414e91cc7e8ae72a9623e0370 100644 --- a/services/core/pom.xml +++ b/services/core/pom.xml @@ -11,7 +11,7 @@ <groupId>org.mte.numecoeval</groupId> <artifactId>core</artifactId> - <version>1.3.0</version> + <version>1.4.0</version> <name>core</name> <packaging>pom</packaging> <description>Projet parent du projet NumEcoEval</description>