Skip to content

Commit

Permalink
Changement de référentiels
Browse files Browse the repository at this point in the history
  • Loading branch information
NerOcrO committed Apr 29, 2024
1 parent c4b5ed2 commit 0b5def1
Show file tree
Hide file tree
Showing 32 changed files with 1,212 additions and 252 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ node_modules
tsconfig.tsbuildinfo
.env.local
.env.prod
infra/roles/referential/files/input_ref*

# yarn
**/.yarn/*
Expand Down
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@

- `yarn`
- `npx husky init`
- `cp .env .env.local` (Remplir les variables affectées par "A_REMPLIR")
- `yarn start:db` (il se peut que le container Kafka ne se lance pas du premier coup, relancer une seconde fois)
- Ajouter les différents référentiels dans `infra/roles/referential/files/input_ref`, il faut les demander à Nathalie Baudiniere
- `yarn load_ref`
- `cp .env .env.local` (remplir les variables affectées par "A_REMPLIR")
- `yarn start:db` (il se peut que le container Kafka ne se lance pas du premier coup, le relancer)
- `yarn load_referentiels`
- `yarn dev`

## NumEcoEval
Expand Down Expand Up @@ -90,7 +89,15 @@ Plage est le service d'authentification.
- [Documentation pour créer un compte de test](https://atih.atlassian.net/wiki/spaces/PUBLIC/pages/2979692685/Plage)
- [Documentation technique](https://atih.atlassian.net/wiki/external/YjE4MTQzOGU0YTNmNDFjNDg3MDcxMjY4NThkMzYzNGE)

## Points d'attention
## Les référentiels

A savoir lors d'une mise à jour des référentiels au format CSV :

- Les identifiants doivent être exactement les même, aucune typo (majuscule, caractère accentué,…), pas d'espaces en trop…
- Séparateur ";"
- Écrire les (types) équipements dans le même ordre

## Points d'attention pour le futur

- La mise à jour de NumEcoEval peut être douloureuse parce que
- la plupart des appels se font directement sur la base de données (suppression, modification...) car les routes n'existent pas
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
modeleEquipementSource;refEquipementCible
Standard - bureautique - 13 pouces;ordinateur-portable-1
Puissante - station de travail -15 pouces;ordinateur-portable-2
Tous types d’ordinateur fixe;ordinateur-fixe-1
Entrée de gamme - LCD - 24 pouces;ecran-1
Milieu de gamme - LCD - 32 pouces;ecran-2
Haut de gamme - OLED;ecran-3
Tous types de serveur rack;serveur-rack-1
Tous types de baie de stockage;baie-stockage-1
Tous types de baie NAS;baie-nas-1
Tous types de commutateur;commutateur-1
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
type_equipement_id;equipement_id
Ordinateur portable;ordinateur-portable-1
Ordinateur portable;ordinateur-portable-2
Écran;ecran-1
Écran;ecran-2
Écran;ecran-3
Ordinateur fixe - sans écran;ordinateur-fixe-1
Serveur rack;serveur-rack-1
Baie de stockage;baie-stockage-1
Baie NAS;baie-nas-1
Commutateur réseau;commutateur-1
6 changes: 6 additions & 0 deletions infra/roles/referential/files/input_ref/criteres.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
nomCritere;description;unite
Climate change;Greenhouse gases (GHG) are gaseous components which absorb the infrared radiation emitted by the earth's surface 1 and thus contribute to the greenhouse effect.;kg CO2 eq
Particulate matter and respiratory inorganics;The presence of small-diameter fine particles in the air - especially those with a diameter of less than 10 microns - represents a human health problem, since their inhalation can cause respiratory and cardiovascular problems.;Disease incidence
Ionising radiation;Corresponds to the effects of radioactivity. This impact corresponds to the radioactive waste resulting from the production of nuclear electricity.;kBq U-235 eq
Acidification;Air acidification is linked to emissions of nitrogen oxides, sulfur oxides, ammonia and hydrochloric acid. These pollutants turn into acids in the presence of moisture, and their fallout can damage ecosystems as well as buildings. ;mol H+ eq
Resource use (minerals and metals);Industrial exploitation leads to a decrease in available resources whose reserves are limited. This indicator assesses the amount of mineral and metallic resources extracted from nature as if they were antimony.;kg Sb eq
5 changes: 5 additions & 0 deletions infra/roles/referential/files/input_ref/etapes.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
code;libelle
FABRICATION;Manufacturing
DISTRIBUTION;Transportation
UTILISATION;Using
FIN_DE_VIE;End of Life
3 changes: 3 additions & 0 deletions infra/roles/referential/files/input_ref/hypotheses.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
cle;source;valeur
PUEParDefaut;SSG;1.75
dureeVieParDefaut;SSG;2
201 changes: 201 additions & 0 deletions infra/roles/referential/files/input_ref/impactequipements.csv

Large diffs are not rendered by default.

691 changes: 691 additions & 0 deletions infra/roles/referential/files/input_ref/mixelecs.csv

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions infra/roles/referential/files/input_ref/typeEquipement.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
type;serveur;commentaire;dureeVieDefaut;refEquipementParDefaut;source
Ordinateur portable;;Durée de vie dans Base IMPACTS numérique v1.5;5;ordinateur-portable-1;
Ordinateur fixe - sans écran;;Durée de vie dans Base IMPACTS numérique v1.5;6;ordinateur-fixe-1;
Écran;;Durée de vie dans Base IMPACTS numérique v1.5;7;ecran-2;
Serveur rack;true;Durée de vie dans Ademe - Rapport septembre 2022 - évaluation de l’impact environnemental d’un ensemble de produits reconditionnés;5;serveur-rack-1;
Baie de stockage;;Durée de vie moyenne par Octo;8;baie-stockage-1;
Baie NAS;;Durée de vie moyenne par Octo;8;baie-nas-1;
Commutateur réseau;;Durée de vie moyenne par Octo;8;commutateur-1;
8 changes: 0 additions & 8 deletions infra/roles/referential/files/load_referentiels.sh

This file was deleted.

14 changes: 14 additions & 0 deletions infra/roles/referential/files/load_referentiels_local.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash

REFERENTIELS="criteres etapes hypotheses typeEquipement correspondanceRefEquipement impactequipements mixelecs"

for referentiel in $REFERENTIELS; do
curl -s -XPOST http://localhost:18080/referentiel/$referentiel/csv --form file=@input_ref/$referentiel.csv
echo ""
done

cat ref_correspondance_type_equipement.sql | docker exec -i postgresdb psql -U postgres postgres

docker cp input_ref/correspondanceTypeEquipement.csv postgresdb:/docker-entrypoint-initdb.d/correspondanceTypeEquipement.csv

docker exec -i postgresdb psql -U postgres postgres -c "\copy ref_correspondance_type_equipement FROM '/docker-entrypoint-initdb.d/correspondanceTypeEquipement.csv' DELIMITER ';' CSV HEADER"
22 changes: 22 additions & 0 deletions infra/roles/referential/files/load_referentiels_prod.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash

REFERENTIELS="criteres etapes hypotheses typeEquipement correspondanceRefEquipement impactequipements mixelecs"

for referentiel in $REFERENTIELS; do
# Attention, manipulations pour que cet import fonctionne :
# - Modifier sur le VM docker-compose.yml pour y ajouter le port 18080 au service api-rest-referentiels
# - docker compose --env-file .env.prod up -d api-rest-referentiels
# - Lancer l'import
# - Retirer le port dans docker-compose.yml
# - docker compose --env-file .env.prod up -d api-rest-referentiels
curl -s -XPOST http://localhost:18080/referentiel/$referentiel/csv --form file=@input_ref/$referentiel.csv
echo ""
done

. ../.env.prod

cat ./ref_correspondance_type_equipement.sql | docker exec -i postgresdb psql -U $POSTGRES_USER postgres

docker cp input_ref/correspondanceTypeEquipement.csv postgresdb:/docker-entrypoint-initdb.d/correspondanceTypeEquipement.csv

docker exec -i postgresdb psql -U $POSTGRES_USER postgres -c "\copy ref_correspondance_type_equipement FROM '/docker-entrypoint-initdb.d/correspondanceTypeEquipement.csv' DELIMITER ';' CSV HEADER"
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS ref_correspondance_type_equipement (
type_equipement_id varchar(100) NOT NULL,
equipement_id varchar(100) NOT NULL
);

TRUNCATE TABLE ref_correspondance_type_equipement;
2 changes: 1 addition & 1 deletion infra/roles/referential/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
dest: .

- name: Install referentials
shell: bash load_ref.sh
shell: bash load_referentiels_prod.sh
args:
chdir: files
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"dev-https": "next dev --experimental-https",
"lint:css": "stylelint 'src/**/*.css'",
"lint:typescript": "eslint . --ext .tsx,.ts --max-warnings=0",
"load_referentiels": "cd infra/roles/referential/files && bash load_referentiels.sh",
"load_referentiels": "cd infra/roles/referential/files && bash load_referentiels_local.sh",
"prepare": "husky",
"prisma:generate": "npx prisma generate",
"psql:local": "docker exec -it postgresdb psql -U postgres postgres",
Expand Down
13 changes: 12 additions & 1 deletion prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,21 @@ model ind_indicateur_impact_equipement_physique {
nom_source_donnee_discriminator String
}

model ref_correspondance_type_equipement {
ref_correspondance_ref_eqp ref_correspondance_ref_eqp @relation(fields: [equipement_id], references: [ref_equipement_cible])
equipement_id String @id
ref_type_equipement ref_type_equipement @relation(fields: [type_equipement_id], references: [type])
type_equipement_id String
}

model ref_correspondance_ref_eqp {
modele_equipement_source String @unique
ref_equipement_cible String @id
equipements ref_correspondance_type_equipement[]
}

model ref_type_equipement {
type String @unique
type String @unique
modeles ref_correspondance_type_equipement[]
}
77 changes: 68 additions & 9 deletions src/app/(connecte)/indicateurs-cles/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { getProfileAtih } from '../../../authentification'
import Breadcrumb from '../../../components/commun/Breadcrumb'
import IndicateursCles from '../../../components/IndicateursCles/IndicateursCles'
import { Criteres, EtapesAcv, IndicateursSommesViewModel, IndicateursViewModel } from '../../../components/viewModel'
import { EquipementPhysiqueModel, recupererLesReferentielsEquipementsRepository } from '../../../repository/equipementsRepository'
import { IndicateursSommesModel, recupererIndicateursEquipementsPhysiquesRepository, recupererIndicateursEquipementsPhysiquesSommesRepository } from '../../../repository/indicateursRepository'

const title = 'Indicateurs clés'
Expand Down Expand Up @@ -35,7 +36,11 @@ export default async function Page({ searchParams }: PageProps): Promise<ReactEl

const indicateursSommesModel = await recupererIndicateursEquipementsPhysiquesSommesRepository(profile.nomEtablissement, searchParams.nomInventaire)

const indicateursSommesViewModel = transformIndicateursSommesModelToViewModel(indicateursSommesModel)
const referentielsEquipementsModel = await recupererLesReferentielsEquipementsRepository()

const referentielsEquipementsViewModel = tranformReferentielsEquipementsToViewModel(referentielsEquipementsModel)

const indicateursSommesViewModel = transformIndicateursSommesModelToViewModel(indicateursSommesModel, referentielsEquipementsViewModel)

const indicateursViewModel = transformIndicateursModelToViewModel(indicateursModel)

Expand All @@ -50,6 +55,7 @@ export default async function Page({ searchParams }: PageProps): Promise<ReactEl
indicateursViewModel={indicateursViewModel}
nomEtablissement={profile.nomEtablissement}
nomInventaire={searchParams.nomInventaire}
referentielsEquipementsViewModel={referentielsEquipementsViewModel}
/>
</>
)
Expand Down Expand Up @@ -108,16 +114,69 @@ function transformIndicateursModelToViewModel(indicateursModel: ind_indicateur_i
}
}

function transformIndicateursSommesModelToViewModel(indicateursSommesModel: IndicateursSommesModel[]): IndicateursSommesViewModel[] {
return indicateursSommesModel.map((indicateurSomme): IndicateursSommesViewModel => {
return {
etapeAcv: indicateurSomme.etapeacv as `${EtapesAcv}`,
impact: indicateurSomme._sum.impact_unitaire,
typeEquipement: indicateurSomme.type_equipement,
}
})
function transformIndicateursSommesModelToViewModel(
indicateursSommesModel: IndicateursSommesModel[],
referentielsEquipementsViewModel: string[]
): IndicateursSommesViewModel[] {
return indicateursSommesModel
.map((indicateurSomme): IndicateursSommesViewModel => {
return {
etapeAcv: indicateurSomme.etapeacv as `${EtapesAcv}`,
impact: indicateurSomme._sum.impact_unitaire,
typeEquipement: indicateurSomme.type_equipement,
}
})
.sort(sortByTypeEquipementAndEtapeAcv(referentielsEquipementsViewModel))
}

function tranformReferentielsEquipementsToViewModel(referentielsEquipementsModel: EquipementPhysiqueModel[]): string[] {
return referentielsEquipementsModel.map((referentielEquipementModel): string => referentielEquipementModel.type)
}

function deuxChiffresApresLaVirgule(chiffre: number): string {
return Number(chiffre.toFixed(2)).toLocaleString()
}

function sortByTypeEquipementAndEtapeAcv(referentielsEquipementsViewModel: string[]) {
return (a: IndicateursSommesViewModel, b: IndicateursSommesViewModel) => {
let etapeAcvA = '0'
let etapeAcvB = '0'

const cyclesDeVie = [
'FABRICATION',
'DISTRIBUTION',
'UTILISATION',
'FIN_DE_VIE',
]

for (let poids = 0; poids < referentielsEquipementsViewModel.length; poids++) {
if (a.typeEquipement === referentielsEquipementsViewModel[poids]) {
etapeAcvA = poids.toString()
}

if (b.typeEquipement === referentielsEquipementsViewModel[poids]) {
etapeAcvB = poids.toString()
}
}

for (let poids = 0; poids < cyclesDeVie.length; poids++) {
if (a.etapeAcv === cyclesDeVie[poids]) {
etapeAcvA += poids.toString()
}

if (b.etapeAcv === cyclesDeVie[poids]) {
etapeAcvB += poids.toString()
}
}

if (etapeAcvA > etapeAcvB) {
return 1
}

if (etapeAcvA < etapeAcvB) {
return -1
}

return 0
}
}
57 changes: 25 additions & 32 deletions src/app/(connecte)/inventaire/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { en_equipement_physique, ref_correspondance_ref_eqp, ref_type_equipement } from '@prisma/client'
import { en_equipement_physique } from '@prisma/client'
import { Metadata } from 'next'
import { notFound } from 'next/navigation'
import { ReactElement } from 'react'
Expand All @@ -7,9 +7,8 @@ import { getProfileAtih } from '../../../authentification'
import Breadcrumb from '../../../components/commun/Breadcrumb'
import Inventaire from '../../../components/Inventaire/Inventaire'
import { ModeleReducer } from '../../../components/Inventaire/useEquipement'
import { EquipementsAvecSesModelesViewModel, NomModeleViewModel, StatutsInventaire } from '../../../components/viewModel'
import { recupererEquipementsPhysiquesRepository, recupererTypesEquipementRepository } from '../../../repository/equipementsRepository'
import { recupererNomsModelesRepository } from '../../../repository/modelesRepository'
import { EquipementsAvecSesModelesViewModel, StatutsInventaire } from '../../../components/viewModel'
import { EquipementPhysiqueModel, recupererLesEquipementsEnregistresRepository, recupererLesReferentielsEquipementsRepository } from '../../../repository/equipementsRepository'

const title = 'Renseigner les équipements'
export const metadata: Metadata = {
Expand All @@ -30,58 +29,52 @@ export default async function Page({ searchParams }: PageProps): Promise<ReactEl

const profile = await getProfileAtih()

const typesEquipementModel = await recupererTypesEquipementRepository()
const nomsModelesModel = await recupererNomsModelesRepository()
const equipementsModel = await recupererEquipementsPhysiquesRepository(profile.nomEtablissement, searchParams.nomInventaire)
const equipementsReferentielsModel = await recupererLesReferentielsEquipementsRepository()

const equipementsAvecSesModelesViewModel = transformTypesEquipementModelToViewModel(typesEquipementModel, equipementsModel)
const nomsModelesViewModel = transformNomsModelesModelToViewModel(nomsModelesModel)
const equipementsEnregistresModel = await recupererLesEquipementsEnregistresRepository(profile.nomEtablissement, searchParams.nomInventaire)

const equipementsAvecSesModelesViewModel = transformTypesEquipementModelToViewModel(equipementsReferentielsModel, equipementsEnregistresModel)

const statut = searchParams.statut === undefined ? StatutsInventaire.EN_ATTENTE : searchParams.statut as StatutsInventaire
const dateInventaire = equipementsAvecSesModelesViewModel.length > 0
? equipementsAvecSesModelesViewModel[0].dateInventaire.toLocaleDateString('fr-FR')
: new Date().toLocaleDateString('fr-FR')
const dateInventaire = equipementsEnregistresModel.length === 0 ? new Date() : equipementsEnregistresModel[0].date_lot

return (
<>
<Breadcrumb label={title} />
<Inventaire
dateInventaire={dateInventaire}
dateInventaire={dateInventaire.toLocaleDateString('fr-FR')}
equipementsAvecSesModelesViewModel={equipementsAvecSesModelesViewModel}
nomEtablissement={profile.nomEtablissement}
nomInventaire={searchParams.nomInventaire}
nomsModelesViewModel={nomsModelesViewModel}
statut={statut}
/>
</>
)
}

function transformNomsModelesModelToViewModel(nomsModelesModel: ref_correspondance_ref_eqp[]): NomModeleViewModel[] {
return nomsModelesModel.map((nomModeleModel): NomModeleViewModel => {
return {
modele: nomModeleModel.modele_equipement_source,
}
})
}

function transformTypesEquipementModelToViewModel(
typesEquipementModel: ref_type_equipement[],
equipementsModel: en_equipement_physique[]
equipementsReferentielsModel: EquipementPhysiqueModel[],
equipementsEnregistresModel: en_equipement_physique[]
): EquipementsAvecSesModelesViewModel[] {
return typesEquipementModel.map((typeEquipement): EquipementsAvecSesModelesViewModel => {
return equipementsReferentielsModel.map((equipementReferentielModel): EquipementsAvecSesModelesViewModel => {
return {
dateInventaire: equipementsModel.length === 0 ? new Date() : equipementsModel[0].date_lot,
modeles: equipementsModel
.filter((equipement): boolean => equipement.type === typeEquipement.type)
.map((equipement): ModeleReducer => {
modeles: equipementReferentielModel.modeles
.map((modele): ModeleReducer => {
let quantite = 0
const equipementsModelFiltre = equipementsEnregistresModel
.filter((equipementEnregistreModel): boolean => equipementEnregistreModel.modele === modele.ref_correspondance_ref_eqp.modele_equipement_source)

if (equipementsModelFiltre.length > 0) {
quantite = equipementsModelFiltre[0].quantite
}

return {
id: crypto.randomUUID(),
nomModele: equipement.modele,
quantite: equipement.quantite,
nomModele: modele.ref_correspondance_ref_eqp.modele_equipement_source,
quantite,
}
}),
type: typeEquipement.type,
type: equipementReferentielModel.type,
}
})
}
Loading

0 comments on commit 0b5def1

Please sign in to comment.