From 5b1d5350b928b1a7460d7e35511c3b4c7cfa8d6e Mon Sep 17 00:00:00 2001 From: Fred <98240+farnoux@users.noreply.github.com> Date: Tue, 24 Dec 2024 20:02:48 +0100 Subject: [PATCH] Remove duplicate schemas for indicateur source and valeur --- .../Accueil/EtatDesLieux/IndicateursCard.tsx | 4 +- .../Accueil/data/useIndicateurSummary.ts | 6 +- .../Indicateur/detail/DataSourceTooltip.tsx | 5 +- .../pages/collectivite/Indicateurs/types.ts | 12 -- .../shared/models/membre.table.ts | 4 +- .../controllers/trajectoire-snbc.e2e-spec.ts | 19 +-- .../controllers/trajectoires.controller.ts | 3 +- backend/src/indicateurs/index-domain.ts | 3 + ...calcul-trajectoire-response-donnees.dto.ts | 20 ++- .../models/calcul-trajectoire.response.ts | 25 ++-- .../models/indicateur-definition.table.ts | 27 ++-- .../indicateur-source-metadonnee.table.ts | 20 +-- .../models/indicateur-source.table.ts | 12 +- .../models/indicateur-valeur.table.ts | 131 +++++++----------- .../upsert-indicateurs-valeurs.request.ts | 4 +- .../verification-trajectoire.response.ts | 4 +- .../services/export-indicateurs.service.ts | 32 ++--- .../services/indicateur-sources.service.ts | 12 +- .../services/indicateurs.service.spec.ts | 37 ++--- .../services/indicateurs.service.ts | 82 ++++++----- .../trajectoires-data.service.spec.ts | 11 +- .../services/trajectoires-data.service.ts | 42 +++--- .../trajectoires-spreadsheet.service.ts | 22 +-- .../trajectoire-snbc-calcul-retour.ts | 4 +- ...t-personnalisation-consequences.request.ts | 4 +- .../get-personnalisation-regles.request.ts | 4 +- .../compute-score/compute-score.router.ts | 6 +- .../referentiels-scoring.controller.ts | 16 +-- .../referentiels-scoring.e2e-spec.ts | 6 +- .../controllers/referentiels.controller.ts | 6 +- .../models/action-definition.table.ts | 4 +- .../models/action-relation.table.ts | 4 +- .../models/client-scores.table.ts | 4 +- .../models/get-check-scores.response.ts | 4 +- .../models/get-referentiel-scores.response.ts | 4 +- .../models/get-score-snapshots.response.ts | 4 +- .../models/labellisation-audit.table.ts | 4 +- .../models/labellisation-demande.table.ts | 4 +- .../models/post-audit-scores.table.ts | 4 +- .../models/pre-audit-scores.table.ts | 4 +- .../referentiels/models/referentiel.enum.ts | 30 ++-- .../services/labellisation.service.ts | 4 +- .../referentiels-scoring-snapshots.service.ts | 12 +- .../services/referentiels-scoring.service.ts | 38 ++--- .../services/referentiels.service.spec.ts | 16 +-- .../services/referentiels.service.ts | 36 ++--- .../snapshots/score-snaphots.router.ts | 10 +- .../score-snapshots.router.e2e-spec.ts | 14 +- .../update-action-statut.router.e2e-spec.ts | 4 +- .../indicateurs/actions/indicateur.fetch.ts | 2 +- .../actions/indicateur.save.test.ts | 6 +- .../indicateurs/actions/indicateur.save.ts | 32 +++-- .../indicateurs/actions/source.fetch.test.ts | 20 --- .../src/indicateurs/actions/source.fetch.ts | 15 -- packages/api/src/indicateurs/domain/index.ts | 3 +- .../src/indicateurs/domain/source.schema.ts | 34 ----- .../src/indicateurs/domain/valeur.schema.ts | 80 +++++++---- .../src/referentiel/domain/action.schema.ts | 4 +- 58 files changed, 463 insertions(+), 520 deletions(-) delete mode 100644 packages/api/src/indicateurs/actions/source.fetch.test.ts delete mode 100644 packages/api/src/indicateurs/actions/source.fetch.ts delete mode 100644 packages/api/src/indicateurs/domain/source.schema.ts diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/EtatDesLieux/Accueil/EtatDesLieux/IndicateursCard.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/EtatDesLieux/Accueil/EtatDesLieux/IndicateursCard.tsx index 216865a739..dcfc031980 100644 --- a/app.territoiresentransitions.react/src/app/pages/collectivite/EtatDesLieux/Accueil/EtatDesLieux/IndicateursCard.tsx +++ b/app.territoiresentransitions.react/src/app/pages/collectivite/EtatDesLieux/Accueil/EtatDesLieux/IndicateursCard.tsx @@ -1,15 +1,15 @@ -import { Referentiel } from '@/api/referentiel/domain/enum.schema'; import { referentielToName } from '@/app/app/labels'; import AccueilCard from '@/app/app/pages/collectivite/EtatDesLieux/Accueil/EtatDesLieux/AccueilCard'; import { makeCollectiviteTousLesIndicateursUrl } from '@/app/app/paths'; import { useFonctionTracker } from '@/app/core-logic/hooks/useFonctionTracker'; +import { ReferentielId } from '@/domain/referentiels'; import { Button } from '@/ui'; import { useIndicateurSummary } from '../data/useIndicateurSummary'; import { useOpenDataIndicateursCount } from '../data/useOpenDataIndicateurs'; type IndicateursCardProps = { collectiviteId: number; - referentielId: Referentiel; + referentielId: ReferentielId; }; /** diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/EtatDesLieux/Accueil/data/useIndicateurSummary.ts b/app.territoiresentransitions.react/src/app/pages/collectivite/EtatDesLieux/Accueil/data/useIndicateurSummary.ts index 313daffb1c..8495d7ea34 100644 --- a/app.territoiresentransitions.react/src/app/pages/collectivite/EtatDesLieux/Accueil/data/useIndicateurSummary.ts +++ b/app.territoiresentransitions.react/src/app/pages/collectivite/EtatDesLieux/Accueil/data/useIndicateurSummary.ts @@ -1,11 +1,11 @@ -import { Referentiel } from '@/api/referentiel/domain/enum.schema'; import { supabaseClient } from '@/app/core-logic/api/supabase'; import { useCollectiviteId } from '@/app/core-logic/hooks/params'; +import { ReferentielId } from '@/domain/referentiels'; import { useQuery } from 'react-query'; const fetchIndicateurSummary = async ( collectivite_id: number, - referentiel: Referentiel + referentiel: ReferentielId ) => { const { error, data } = await supabaseClient .from('indicateur_summary') @@ -20,7 +20,7 @@ const fetchIndicateurSummary = async ( /** * Récupère le summary des indicateurs d'un référentiel pour une collectivité donnée */ -export const useIndicateurSummary = (referentiel: Referentiel) => { +export const useIndicateurSummary = (referentiel: ReferentielId) => { const collectiviteId = useCollectiviteId(); return useQuery(['indicateur_summary', collectiviteId, referentiel], () => { diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/Indicateurs/Indicateur/detail/DataSourceTooltip.tsx b/app.territoiresentransitions.react/src/app/pages/collectivite/Indicateurs/Indicateur/detail/DataSourceTooltip.tsx index 39b709031a..4678af288e 100644 --- a/app.territoiresentransitions.react/src/app/pages/collectivite/Indicateurs/Indicateur/detail/DataSourceTooltip.tsx +++ b/app.territoiresentransitions.react/src/app/pages/collectivite/Indicateurs/Indicateur/detail/DataSourceTooltip.tsx @@ -1,4 +1,4 @@ -import { Indicateurs } from '@/api'; +import { Valeur } from '@/api/indicateurs/domain'; import { Tooltip } from '@/ui'; /** @@ -9,7 +9,8 @@ export const DataSourceTooltip = ({ metadonnee, children, }: { - metadonnee: Indicateurs.domain.SourceMetadonnee; + metadonnee: NonNullable; + // metadonnee: ReturnType['metadonnee']; children: JSX.Element; }) => { return ( diff --git a/app.territoiresentransitions.react/src/app/pages/collectivite/Indicateurs/types.ts b/app.territoiresentransitions.react/src/app/pages/collectivite/Indicateurs/types.ts index 78191a1aaf..8f1f41ac88 100644 --- a/app.territoiresentransitions.react/src/app/pages/collectivite/Indicateurs/types.ts +++ b/app.territoiresentransitions.react/src/app/pages/collectivite/Indicateurs/types.ts @@ -6,19 +6,7 @@ export type SourceType = 'resultat' | 'objectif'; /** Item dans une liste d'indicateurs (avant que le détail pour la vignette ne soit chargé) */ export type TIndicateurListItem = Indicateurs.domain.IndicateurListItem; -/** Item détaillé pour la vignette graphique dans une liste d'indicateurs */ -export type TIndicateurChartInfo = Indicateurs.domain.IndicateurChartInfo; - -export type IndicateurInsert = Indicateurs.domain.IndicateurDefinitionInsert; - -export type TIndicateurPredefiniEnfant = TIndicateurPredefini & { - parent: string; -}; - export type TIndicateurPredefini = Indicateurs.domain.IndicateurDefinitionPredefini; -export type TIndicateurPersonnalise = - Indicateurs.domain.IndicateurDefinitionPersonalise; - export type TIndicateurDefinition = Indicateurs.domain.IndicateurDefinition; diff --git a/backend/src/collectivites/shared/models/membre.table.ts b/backend/src/collectivites/shared/models/membre.table.ts index fc251072ec..c2bbf989ba 100644 --- a/backend/src/collectivites/shared/models/membre.table.ts +++ b/backend/src/collectivites/shared/models/membre.table.ts @@ -8,7 +8,7 @@ import { } from 'drizzle-orm/pg-core'; import { createInsertSchema } from 'drizzle-zod'; import { authUsersTable } from '../../../auth/models/auth-users.table'; -import { referentielEnum } from '../../../referentiels/models/referentiel.enum'; +import { referentielIdPgEnum } from '../../../referentiels/models/referentiel.enum'; import { createdAt, modifiedAt } from '../../../utils/column.utils'; import { collectiviteTable } from './collectivite.table'; import { membreFonctionEnum } from './membre-fonction.enum'; @@ -24,7 +24,7 @@ export const membreTable = pgTable( .notNull(), fonction: membreFonctionEnum('fonction'), detailsFonction: text('details_fonction'), - champIntervention: referentielEnum('champ_intervention').array(), + champIntervention: referentielIdPgEnum('champ_intervention').array(), estReferent: boolean('est_referent'), createdAt, modifiedAt, diff --git a/backend/src/indicateurs/controllers/trajectoire-snbc.e2e-spec.ts b/backend/src/indicateurs/controllers/trajectoire-snbc.e2e-spec.ts index 8b30b50a6d..eb99f5fd9f 100644 --- a/backend/src/indicateurs/controllers/trajectoire-snbc.e2e-spec.ts +++ b/backend/src/indicateurs/controllers/trajectoire-snbc.e2e-spec.ts @@ -1,5 +1,5 @@ import { CalculTrajectoireResultatMode } from '@/backend/indicateurs/models/calcul-trajectoire.request'; -import { CalculTrajectoireResponseType } from '@/backend/indicateurs/models/calcul-trajectoire.response'; +import { CalculTrajectoireResponse } from '@/backend/indicateurs/models/calcul-trajectoire.response'; import { INestApplication } from '@nestjs/common'; import { default as request } from 'supertest'; import { getTestApp } from '../../../test/app-utils'; @@ -27,7 +27,8 @@ describe('Calcul de trajectoire SNBC', () => { .set('Authorization', `Bearer ${yoloDodoToken}`) .expect(401) .expect({ - message: "Droits insuffisants, l'utilisateur 17440546-f389-4d4f-bfdb-b0c94a1bd0f9 n'a pas l'autorisation indicateurs.trajectoires.lecture sur la ressource Collectivité 3", + message: + "Droits insuffisants, l'utilisateur 17440546-f389-4d4f-bfdb-b0c94a1bd0f9 n'a pas l'autorisation indicateurs.trajectoires.lecture sur la ressource Collectivité 3", error: 'Unauthorized', statusCode: 401, }); @@ -39,7 +40,8 @@ describe('Calcul de trajectoire SNBC', () => { .set('Authorization', `Bearer ${yoloDodoToken}`) .expect(401) .expect({ - message: "Droits insuffisants, l'utilisateur 17440546-f389-4d4f-bfdb-b0c94a1bd0f9 n'a pas l'autorisation indicateurs.trajectoires.edition sur la ressource Collectivité 3", + message: + "Droits insuffisants, l'utilisateur 17440546-f389-4d4f-bfdb-b0c94a1bd0f9 n'a pas l'autorisation indicateurs.trajectoires.edition sur la ressource Collectivité 3", error: 'Unauthorized', statusCode: 401, }); @@ -286,7 +288,8 @@ describe('Calcul de trajectoire SNBC', () => { .set('Authorization', `Bearer ${yoloDodoToken}`) .expect(401) .expect({ - message: "Droits insuffisants, l'utilisateur 17440546-f389-4d4f-bfdb-b0c94a1bd0f9 n'a pas l'autorisation indicateurs.trajectoires.edition sur la ressource Collectivité 3895", + message: + "Droits insuffisants, l'utilisateur 17440546-f389-4d4f-bfdb-b0c94a1bd0f9 n'a pas l'autorisation indicateurs.trajectoires.edition sur la ressource Collectivité 3895", error: 'Unauthorized', statusCode: 401, }); @@ -481,7 +484,7 @@ describe('Calcul de trajectoire SNBC', () => { .get('/trajectoires/snbc?collectiviteId=4936') .set('Authorization', `Bearer ${yoloDodoToken}`) .expect(200); - expect((responseCalcul.body as CalculTrajectoireResponseType).mode).toEqual( + expect((responseCalcul.body as CalculTrajectoireResponse).mode).toEqual( CalculTrajectoireResultatMode.MAJ_SPREADSHEET_EXISTANT ); @@ -510,9 +513,9 @@ describe('Calcul de trajectoire SNBC', () => { .get('/trajectoires/snbc?collectiviteId=4936') .set('Authorization', `Bearer ${yoloDodoToken}`) .expect(200); - expect( - (responseRecalcul.body as CalculTrajectoireResponseType).mode - ).toEqual(CalculTrajectoireResultatMode.DONNEES_EN_BDD); + expect((responseRecalcul.body as CalculTrajectoireResponse).mode).toEqual( + CalculTrajectoireResultatMode.DONNEES_EN_BDD + ); }, 30000); it(`Telechargement du modele`, () => { diff --git a/backend/src/indicateurs/controllers/trajectoires.controller.ts b/backend/src/indicateurs/controllers/trajectoires.controller.ts index a312ade9c8..1a9d063581 100644 --- a/backend/src/indicateurs/controllers/trajectoires.controller.ts +++ b/backend/src/indicateurs/controllers/trajectoires.controller.ts @@ -22,12 +22,13 @@ import { verificationTrajectoireResponseSchema } from '../models/verification-tr import TrajectoiresDataService from '../services/trajectoires-data.service'; import TrajectoiresSpreadsheetService from '../services/trajectoires-spreadsheet.service'; import TrajectoiresXlsxService from '../services/trajectoires-xlsx.service'; +import { extendApi } from '@anatine/zod-openapi'; /** * Création des classes de requête/réponse à partir du schema pour générer automatiquement la documentation OpenAPI et la validation des entrées */ export class CalculTrajectoireResponseClass extends createZodDto( - calculTrajectoireResponseSchema + extendApi(calculTrajectoireResponseSchema) ) {} export class CalculTrajectoireRequestClass extends createZodDto( diff --git a/backend/src/indicateurs/index-domain.ts b/backend/src/indicateurs/index-domain.ts index a10e793525..339a288bd4 100644 --- a/backend/src/indicateurs/index-domain.ts +++ b/backend/src/indicateurs/index-domain.ts @@ -2,3 +2,6 @@ // Exports from this file can be imported with `@/domain/*` alias path. export * from './models/indicateur-definition.table'; +export * from './models/indicateur-source-metadonnee.table'; +export * from './models/indicateur-source.table'; +export * from './models/indicateur-valeur.table'; diff --git a/backend/src/indicateurs/models/calcul-trajectoire-response-donnees.dto.ts b/backend/src/indicateurs/models/calcul-trajectoire-response-donnees.dto.ts index fa0927a4dd..6ccc42dec6 100644 --- a/backend/src/indicateurs/models/calcul-trajectoire-response-donnees.dto.ts +++ b/backend/src/indicateurs/models/calcul-trajectoire-response-donnees.dto.ts @@ -1,16 +1,14 @@ -import { extendApi } from '@anatine/zod-openapi'; import { z } from 'zod'; import { indicateurAvecValeursSchema } from './indicateur-valeur.table'; -export const calculTrajectoireResponseDonneesSchema = extendApi( - z - .object({ - emissionsGes: z.array(indicateurAvecValeursSchema), - consommationsFinales: z.array(indicateurAvecValeursSchema), - sequestrations: z.array(indicateurAvecValeursSchema), - }) - .describe('Données de la trajectoire SNBC') -); -export type CalculTrajectoireResponseDonneesType = z.infer< +export const calculTrajectoireResponseDonneesSchema = z + .object({ + emissionsGes: z.array(indicateurAvecValeursSchema), + consommationsFinales: z.array(indicateurAvecValeursSchema), + sequestrations: z.array(indicateurAvecValeursSchema), + }) + .describe('Données de la trajectoire SNBC'); + +export type CalculTrajectoireResponseDonnees = z.infer< typeof calculTrajectoireResponseDonneesSchema >; diff --git a/backend/src/indicateurs/models/calcul-trajectoire.response.ts b/backend/src/indicateurs/models/calcul-trajectoire.response.ts index 9f6ae9856e..1784589344 100644 --- a/backend/src/indicateurs/models/calcul-trajectoire.response.ts +++ b/backend/src/indicateurs/models/calcul-trajectoire.response.ts @@ -1,23 +1,20 @@ -import { extendApi } from '@anatine/zod-openapi'; import { z } from 'zod'; import { calculTrajectoireResponseDonneesSchema } from './calcul-trajectoire-response-donnees.dto'; import { CalculTrajectoireResultatMode } from './calcul-trajectoire.request'; -export const calculTrajectoireResponseSchema = extendApi( - z - .object({ - mode: z.nativeEnum(CalculTrajectoireResultatMode), - sourcesDonneesEntree: z.string().array(), - indentifiantsReferentielManquantsDonneesEntree: z.array(z.string()), - trajectoire: calculTrajectoireResponseDonneesSchema, - }) - .describe('Réponse du calcul de la trajectoire SNBC') -); -export type CalculTrajectoireResponseType = z.infer< +export const calculTrajectoireResponseSchema = z + .object({ + mode: z.nativeEnum(CalculTrajectoireResultatMode), + sourcesDonneesEntree: z.string().array(), + indentifiantsReferentielManquantsDonneesEntree: z.array(z.string()), + trajectoire: calculTrajectoireResponseDonneesSchema, + }) + .describe('Réponse du calcul de la trajectoire SNBC'); + +export type CalculTrajectoireResponse = z.infer< typeof calculTrajectoireResponseSchema >; -export interface CalculTrajectoireResultType - extends CalculTrajectoireResponseType { +export interface CalculTrajectoireResult extends CalculTrajectoireResponse { spreadsheetId: string; } diff --git a/backend/src/indicateurs/models/indicateur-definition.table.ts b/backend/src/indicateurs/models/indicateur-definition.table.ts index 415755e4ea..de6fd3899d 100644 --- a/backend/src/indicateurs/models/indicateur-definition.table.ts +++ b/backend/src/indicateurs/models/indicateur-definition.table.ts @@ -43,19 +43,22 @@ export const indicateurDefinitionTable = pgTable('indicateur_definition', { createdBy, modifiedBy, }); -export type IndicateurDefinitionType = InferSelectModel< - typeof indicateurDefinitionTable ->; -export type CreateIndicateurDefinitionType = InferInsertModel< - typeof indicateurDefinitionTable ->; + export const indicateurDefinitionSchema = createSelectSchema( indicateurDefinitionTable ); -export const createIndicateurDefinitionSchema = createInsertSchema( +export type IndicateurDefinition = InferSelectModel< + typeof indicateurDefinitionTable +>; + +export const indicateurDefinitionSchemaInsert = createInsertSchema( indicateurDefinitionTable ); -export const minimaleIndicateurDefinitionSchema = +export type IndicateurDefinitionInsert = InferInsertModel< + typeof indicateurDefinitionTable +>; + +export const indicateurDefinitionSchemaEssential = indicateurDefinitionSchema.pick({ id: true, identifiantReferentiel: true, @@ -66,10 +69,10 @@ export const minimaleIndicateurDefinitionSchema = borneMin: true, borneMax: true, }); -export type MinimalIndicateurDefinitionType = z.infer< - typeof minimaleIndicateurDefinitionSchema +export type IndicateurDefinitionEssential = z.infer< + typeof indicateurDefinitionSchemaEssential >; -export type IndicateurDefinitionAvecEnfantsType = IndicateurDefinitionType & { - enfants: IndicateurDefinitionType[] | null; +export type IndicateurDefinitionAvecEnfantsType = IndicateurDefinition & { + enfants: IndicateurDefinition[] | null; }; diff --git a/backend/src/indicateurs/models/indicateur-source-metadonnee.table.ts b/backend/src/indicateurs/models/indicateur-source-metadonnee.table.ts index a1f7e49519..b53ebc1f94 100644 --- a/backend/src/indicateurs/models/indicateur-source-metadonnee.table.ts +++ b/backend/src/indicateurs/models/indicateur-source-metadonnee.table.ts @@ -18,15 +18,19 @@ export const indicateurSourceMetadonneeTable = pgTable( limites: text('limites'), } ); -export type IndicateurSourceMetadonneeType = InferSelectModel< - typeof indicateurSourceMetadonneeTable ->; -export type CreateIndicateurSourceMetadonneeType = InferInsertModel< - typeof indicateurSourceMetadonneeTable ->; -export const indicateurSourceMetadonneeSchema = createSelectSchema( + +export const sourceMetadonneeSchema = createSelectSchema( indicateurSourceMetadonneeTable ); -export const createIndicateurSourceMetadonneeSchema = createInsertSchema( + +export type SourceMetadonnee = InferSelectModel< + typeof indicateurSourceMetadonneeTable +>; + +export const sourceMetadonneeSchemaInsert = createInsertSchema( indicateurSourceMetadonneeTable ); + +export type SourceMetadonneeInsert = InferInsertModel< + typeof indicateurSourceMetadonneeTable +>; diff --git a/backend/src/indicateurs/models/indicateur-source.table.ts b/backend/src/indicateurs/models/indicateur-source.table.ts index 5821d9180e..2edd22063e 100644 --- a/backend/src/indicateurs/models/indicateur-source.table.ts +++ b/backend/src/indicateurs/models/indicateur-source.table.ts @@ -1,14 +1,12 @@ -import { integer, pgTable, text } from 'drizzle-orm/pg-core'; import { InferInsertModel, InferSelectModel } from 'drizzle-orm'; +import { integer, pgTable, text } from 'drizzle-orm/pg-core'; export const indicateurSourceTable = pgTable('indicateur_source', { id: text('id').primaryKey(), libelle: text('libelle').notNull(), ordreAffichage: integer('ordre_affichage'), }); -export type IndicateurSourceType = InferSelectModel< - typeof indicateurSourceTable ->; -export type CreateIndicateurSourceType = InferInsertModel< - typeof indicateurSourceTable ->; + +export type Source = InferSelectModel; + +export type SourceInsert = InferInsertModel; diff --git a/backend/src/indicateurs/models/indicateur-valeur.table.ts b/backend/src/indicateurs/models/indicateur-valeur.table.ts index 38b68d4b2b..f4b32d404d 100644 --- a/backend/src/indicateurs/models/indicateur-valeur.table.ts +++ b/backend/src/indicateurs/models/indicateur-valeur.table.ts @@ -1,5 +1,3 @@ -import { createZodDto } from '@anatine/zod-nestjs'; -import { extendApi } from '@anatine/zod-openapi'; import { InferInsertModel, InferSelectModel } from 'drizzle-orm'; import { date, @@ -19,15 +17,15 @@ import { modifiedBy, } from '../../utils/column.utils'; import { + IndicateurDefinition, indicateurDefinitionSchema, + indicateurDefinitionSchemaEssential, indicateurDefinitionTable, - IndicateurDefinitionType, - minimaleIndicateurDefinitionSchema, } from './indicateur-definition.table'; import { - indicateurSourceMetadonneeSchema, indicateurSourceMetadonneeTable, - IndicateurSourceMetadonneeType, + SourceMetadonnee, + sourceMetadonneeSchema, } from './indicateur-source-metadonnee.table'; export const indicateurValeurTable = pgTable('indicateur_valeur', { @@ -60,93 +58,62 @@ export const indicateurValeurTable = pgTable('indicateur_valeur', { modifiedBy, }); -export type IndicateurValeurType = InferSelectModel< - typeof indicateurValeurTable ->; -export type CreateIndicateurValeurType = InferInsertModel< - typeof indicateurValeurTable ->; export const indicateurValeurSchema = createSelectSchema(indicateurValeurTable); -export const createIndicateurValeurSchema = createInsertSchema( - indicateurValeurTable -); - -export const indicateurValeurGroupeeSchema = extendApi( - indicateurValeurSchema - .pick({ - id: true, - dateValeur: true, - resultat: true, - resultatCommentaire: true, - objectif: true, - objectifCommentaire: true, - metadonneeId: true, - }) - .partial({ - resultat: true, - resultatCommentaire: true, - objectif: true, - objectifCommentaire: true, - metadonneeId: true, - }) -); +export type IndicateurValeur = InferSelectModel; -export type IndicateurValeurGroupeeType = z.infer< - typeof indicateurValeurGroupeeSchema ->; - -export class IndicateurValeurGroupee extends createZodDto( - indicateurValeurGroupeeSchema -) {} - -export const indicateurAvecValeursSchema = extendApi( - z - .object({ - definition: minimaleIndicateurDefinitionSchema, - valeurs: z.array(indicateurValeurGroupeeSchema), - }) - .describe('Indicateur définition et valeurs ordonnées par date') +export const indicateurValeurSchemaInsert = createInsertSchema( + indicateurValeurTable ); - -export type IndicateurAvecValeursType = z.infer< - typeof indicateurAvecValeursSchema +export type IndicateurValeurInsert = InferInsertModel< + typeof indicateurValeurTable >; -export class IndicateurAvecValeursClass extends createZodDto( - indicateurAvecValeursSchema -) {} +export const indicateurValeurGroupeeSchema = indicateurValeurSchema + .pick({ + id: true, + dateValeur: true, + resultat: true, + resultatCommentaire: true, + objectif: true, + objectifCommentaire: true, + metadonneeId: true, + }) + .partial({ + resultat: true, + resultatCommentaire: true, + objectif: true, + objectifCommentaire: true, + metadonneeId: true, + }); -export const indicateurValeursGroupeeParSourceSchema = extendApi( - z - .object({ - source: z.string(), - metadonnees: z.array(indicateurSourceMetadonneeSchema), - valeurs: z.array(indicateurValeurGroupeeSchema), - }) - .describe('Indicateur valeurs pour une source donnée') -); +export const indicateurAvecValeursSchema = z + .object({ + definition: indicateurDefinitionSchemaEssential, + valeurs: z.array(indicateurValeurGroupeeSchema), + }) + .describe('Indicateur définition et valeurs ordonnées par date'); -export class IndicateurValeursGroupeeParSource extends createZodDto( - indicateurValeursGroupeeParSourceSchema -) {} +export type IndicateurAvecValeurs = z.infer; -export const indicateurAvecValeursParSourceSchema = extendApi( - z - .object({ - definition: indicateurDefinitionSchema, - sources: z.record(z.string(), indicateurValeursGroupeeParSourceSchema), - }) - .describe('Filtre de récupération des valeurs des indicateurs') -); +export const indicateurValeursGroupeeParSourceSchema = z + .object({ + source: z.string(), + metadonnees: z.array(sourceMetadonneeSchema), + valeurs: z.array(indicateurValeurGroupeeSchema), + }) + .describe('Indicateur valeurs pour une source donnée'); -export class IndicateurAvecValeursParSource extends createZodDto( - indicateurAvecValeursParSourceSchema -) {} +export const indicateurAvecValeursParSourceSchema = z + .object({ + definition: indicateurDefinitionSchema, + sources: z.record(z.string(), indicateurValeursGroupeeParSourceSchema), + }) + .describe('Filtre de récupération des valeurs des indicateurs'); export interface IndicateurValeurAvecMetadonnesDefinition { - indicateur_valeur: IndicateurValeurType; + indicateur_valeur: IndicateurValeur; - indicateur_definition: IndicateurDefinitionType | null; + indicateur_definition: IndicateurDefinition | null; - indicateur_source_metadonnee: IndicateurSourceMetadonneeType | null; + indicateur_source_metadonnee: SourceMetadonnee | null; } diff --git a/backend/src/indicateurs/models/upsert-indicateurs-valeurs.request.ts b/backend/src/indicateurs/models/upsert-indicateurs-valeurs.request.ts index 75b55eddd5..c03b74cf2c 100644 --- a/backend/src/indicateurs/models/upsert-indicateurs-valeurs.request.ts +++ b/backend/src/indicateurs/models/upsert-indicateurs-valeurs.request.ts @@ -1,14 +1,14 @@ import { createZodDto } from '@anatine/zod-nestjs'; import { extendApi } from '@anatine/zod-openapi'; import { z } from 'zod'; -import { createIndicateurValeurSchema } from './indicateur-valeur.table'; +import { indicateurValeurSchemaInsert } from './indicateur-valeur.table'; export const upsertIndicateursValeursRequestSchema = extendApi( z .object({ valeurs: extendApi( z - .array(createIndicateurValeurSchema) + .array(indicateurValeurSchemaInsert) .min(1) .describe('Liste de valeurs') ), diff --git a/backend/src/indicateurs/models/verification-trajectoire.response.ts b/backend/src/indicateurs/models/verification-trajectoire.response.ts index 515150c151..413670a96b 100644 --- a/backend/src/indicateurs/models/verification-trajectoire.response.ts +++ b/backend/src/indicateurs/models/verification-trajectoire.response.ts @@ -2,7 +2,7 @@ import { extendApi } from '@anatine/zod-openapi'; import { z } from 'zod'; import { epciSchema } from '../../collectivites/shared/models/epci.table'; import { donneesCalculTrajectoireARemplirSchema } from './donnees-calcul-trajectoire-a-remplir.dto'; -import { IndicateurValeurType } from './indicateur-valeur.table'; +import { IndicateurValeur } from './indicateur-valeur.table'; export enum VerificationTrajectoireStatus { COMMUNE_NON_SUPPORTEE = 'commune_non_supportee', @@ -45,5 +45,5 @@ export type VerificationTrajectoireResponseType = z.infer< export interface VerificationTrajectoireResultType extends VerificationTrajectoireResponseType { - valeurs?: IndicateurValeurType[]; + valeurs?: IndicateurValeur[]; } diff --git a/backend/src/indicateurs/services/export-indicateurs.service.ts b/backend/src/indicateurs/services/export-indicateurs.service.ts index d72896c5d6..20d82ef086 100644 --- a/backend/src/indicateurs/services/export-indicateurs.service.ts +++ b/backend/src/indicateurs/services/export-indicateurs.service.ts @@ -1,25 +1,25 @@ +import { PermissionOperation } from '@/backend/auth/authorizations/permission-operation.enum'; +import { PermissionService } from '@/backend/auth/authorizations/permission.service'; +import { ResourceType } from '@/backend/auth/authorizations/resource-type.enum'; import { Injectable, Logger } from '@nestjs/common'; -import { Workbook } from 'exceljs'; import { format } from 'date-fns'; import { uniq } from 'es-toolkit'; +import { Workbook } from 'exceljs'; import { AuthenticatedUser } from '../../auth/models/auth.models'; -import IndicateursService from './indicateurs.service'; -import { ExportIndicateursRequestType } from '../models/export-indicateurs.request'; -import { - IndicateurDefinitionAvecEnfantsType, - MinimalIndicateurDefinitionType, -} from '../models/indicateur-definition.table'; -import { IndicateurValeurAvecMetadonnesDefinition } from '../models/indicateur-valeur.table'; -import { IndicateurSourceMetadonneeType } from '../models/indicateur-source-metadonnee.table'; +import CollectivitesService from '../../collectivites/services/collectivites.service'; import { adjustColumnWidth, BOLD, normalizeWorksheetName, } from '../../utils/excel/excel.utils'; -import CollectivitesService from '../../collectivites/services/collectivites.service'; -import { PermissionService } from '@/backend/auth/authorizations/permission.service'; -import { ResourceType } from '@/backend/auth/authorizations/resource-type.enum'; -import { PermissionOperation } from '@/backend/auth/authorizations/permission-operation.enum'; +import { ExportIndicateursRequestType } from '../models/export-indicateurs.request'; +import { + IndicateurDefinitionAvecEnfantsType, + IndicateurDefinitionEssential, +} from '../models/indicateur-definition.table'; +import { SourceMetadonnee } from '../models/indicateur-source-metadonnee.table'; +import { IndicateurValeurAvecMetadonnesDefinition } from '../models/indicateur-valeur.table'; +import IndicateursService from './indicateurs.service'; @Injectable() export default class ExportIndicateursService { @@ -272,13 +272,13 @@ export default class ExportIndicateursService { adjustColumnWidth(worksheet); } - private getSourceName(source: IndicateurSourceMetadonneeType) { + private getSourceName(source: SourceMetadonnee) { return source.nomDonnees || source.diffuseur || source.producteur; } private sortByDefinitionId( - a: MinimalIndicateurDefinitionType, - b: MinimalIndicateurDefinitionType + a: IndicateurDefinitionEssential, + b: IndicateurDefinitionEssential ) { return `${a.identifiantReferentiel ?? a.id}`.localeCompare( `${b.identifiantReferentiel ?? b.id}`, diff --git a/backend/src/indicateurs/services/indicateur-sources.service.ts b/backend/src/indicateurs/services/indicateur-sources.service.ts index 1569205084..0b9f0b695c 100644 --- a/backend/src/indicateurs/services/indicateur-sources.service.ts +++ b/backend/src/indicateurs/services/indicateur-sources.service.ts @@ -2,13 +2,13 @@ import { Injectable, Logger } from '@nestjs/common'; import { and, eq } from 'drizzle-orm'; import { DatabaseService } from '../../utils/database/database.service'; import { - CreateIndicateurSourceMetadonneeType, indicateurSourceMetadonneeTable, - IndicateurSourceMetadonneeType, + SourceMetadonnee, + SourceMetadonneeInsert, } from '../models/indicateur-source-metadonnee.table'; import { - CreateIndicateurSourceType, indicateurSourceTable, + SourceInsert, } from '../models/indicateur-source.table'; @Injectable() @@ -18,7 +18,7 @@ export default class IndicateurSourcesService { constructor(private readonly databaseService: DatabaseService) {} async createIndicateurSourceMetadonnee( - indicateurSourceMetadonneeType: CreateIndicateurSourceMetadonneeType + indicateurSourceMetadonneeType: SourceMetadonneeInsert ) { this.logger.log( `Création de la metadonnees pour la source d'indicateur ${indicateurSourceMetadonneeType.sourceId} et la date ${indicateurSourceMetadonneeType.dateVersion}` @@ -35,7 +35,7 @@ export default class IndicateurSourcesService { async getIndicateurSourceMetadonnee( sourceId: string, dateVersion: string - ): Promise { + ): Promise { this.logger.log( `Récupération de la metadonnees pour la source d'indicateur ${sourceId} et la date ${dateVersion}` ); @@ -54,7 +54,7 @@ export default class IndicateurSourcesService { : null; } - async upsertIndicateurSource(indicateurSource: CreateIndicateurSourceType) { + async upsertIndicateurSource(indicateurSource: SourceInsert) { this.logger.log(`Upsert de la source d'indicateur ${indicateurSource.id}`); return this.databaseService.db .insert(indicateurSourceTable) diff --git a/backend/src/indicateurs/services/indicateurs.service.spec.ts b/backend/src/indicateurs/services/indicateurs.service.spec.ts index 3b5ddf408d..7d9620a68b 100644 --- a/backend/src/indicateurs/services/indicateurs.service.spec.ts +++ b/backend/src/indicateurs/services/indicateurs.service.spec.ts @@ -2,15 +2,16 @@ import { PermissionService } from '@/backend/auth/authorizations/permission.serv import { Test } from '@nestjs/testing'; import * as _ from 'lodash'; import { DatabaseService } from '../../utils/database/database.service'; -import { IndicateurDefinitionType } from '../models/indicateur-definition.table'; -import { IndicateurSourceMetadonneeType } from '../models/indicateur-source-metadonnee.table'; +import { IndicateurDefinition } from '../models/indicateur-definition.table'; +import { SourceMetadonnee } from '../models/indicateur-source-metadonnee.table'; import { - IndicateurAvecValeursParSource, - IndicateurAvecValeursType, + IndicateurAvecValeurs, + IndicateurValeur, IndicateurValeurAvecMetadonnesDefinition, - IndicateurValeurType, } from '../models/indicateur-valeur.table'; -import IndicateursService from './indicateurs.service'; +import IndicateursService, { + IndicateurAvecValeursParSource, +} from './indicateurs.service'; describe('IndicateursService', () => { let indicateurService: IndicateursService; @@ -31,7 +32,7 @@ describe('IndicateursService', () => { describe('groupeIndicateursValeursParIndicateur', () => { it('Groupe les valeurs par indicateur, trie par date croissante les valeurs', async () => { - const indicateur1: IndicateurDefinitionType = { + const indicateur1: IndicateurDefinition = { id: 456, groupementId: null, collectiviteId: null, @@ -50,7 +51,7 @@ describe('IndicateursService', () => { modifiedBy: null, createdBy: null, }; - const indicateur2: IndicateurDefinitionType = { + const indicateur2: IndicateurDefinition = { id: 457, groupementId: null, collectiviteId: null, @@ -69,7 +70,7 @@ describe('IndicateursService', () => { modifiedBy: null, createdBy: null, }; - const indicateur3: IndicateurDefinitionType = { + const indicateur3: IndicateurDefinition = { id: 458, groupementId: null, collectiviteId: null, @@ -89,14 +90,14 @@ describe('IndicateursService', () => { modifiedBy: null, createdBy: null, }; - const indicateurDefinitions: IndicateurDefinitionType[] = [ + const indicateurDefinitions: IndicateurDefinition[] = [ indicateur1, indicateur2, indicateur3, indicateur1, // duplicate ]; - const indicateurValeurs: IndicateurValeurType[] = [ + const indicateurValeurs: IndicateurValeur[] = [ { id: 10264, collectiviteId: 4936, @@ -151,7 +152,7 @@ describe('IndicateursService', () => { indicateurValeurs, indicateurDefinitions ); - const expectedIndicateurValeursGroupees: IndicateurAvecValeursType[] = [ + const expectedIndicateurValeursGroupees: IndicateurAvecValeurs[] = [ { definition: { id: 456, @@ -206,7 +207,7 @@ describe('IndicateursService', () => { describe('groupeIndicateursValeursParIndicateurEtSource', () => { it('Groupe les valeurs par indicateur et par source, trie par date croissante les valeurs', async () => { - const indicateur1: IndicateurDefinitionType = { + const indicateur1: IndicateurDefinition = { id: 456, groupementId: null, collectiviteId: null, @@ -225,7 +226,7 @@ describe('IndicateursService', () => { modifiedBy: null, createdBy: null, }; - const indicateur2: IndicateurDefinitionType = { + const indicateur2: IndicateurDefinition = { id: 457, groupementId: null, collectiviteId: null, @@ -244,7 +245,7 @@ describe('IndicateursService', () => { modifiedBy: null, createdBy: null, }; - const indicateur3: IndicateurDefinitionType = { + const indicateur3: IndicateurDefinition = { id: 458, groupementId: null, collectiviteId: null, @@ -264,14 +265,14 @@ describe('IndicateursService', () => { modifiedBy: null, createdBy: null, }; - const indicateurDefinitions: IndicateurDefinitionType[] = [ + const indicateurDefinitions: IndicateurDefinition[] = [ indicateur1, indicateur2, indicateur3, indicateur1, // duplicate ]; - const indicateurMetadonnees: IndicateurSourceMetadonneeType[] = [ + const indicateurMetadonnees: SourceMetadonnee[] = [ { id: 1, sourceId: 'rare', @@ -294,7 +295,7 @@ describe('IndicateursService', () => { }, ]; - const indicateurValeurs: IndicateurValeurType[] = [ + const indicateurValeurs: IndicateurValeur[] = [ { id: 10264, collectiviteId: 4936, diff --git a/backend/src/indicateurs/services/indicateurs.service.ts b/backend/src/indicateurs/services/indicateurs.service.ts index 69f79ce059..57ebbafc5d 100644 --- a/backend/src/indicateurs/services/indicateurs.service.ts +++ b/backend/src/indicateurs/services/indicateurs.service.ts @@ -1,6 +1,8 @@ import { PermissionOperation } from '@/backend/auth/authorizations/permission-operation.enum'; import { PermissionService } from '@/backend/auth/authorizations/permission.service'; import { ResourceType } from '@/backend/auth/authorizations/resource-type.enum'; +import { createZodDto } from '@anatine/zod-nestjs'; +import { extendApi } from '@anatine/zod-openapi'; import { Injectable, Logger } from '@nestjs/common'; import { aliasedTable, @@ -28,27 +30,39 @@ import { DeleteIndicateursValeursRequestType } from '../models/delete-indicateur import { GetIndicateursValeursRequestType } from '../models/get-indicateurs.request'; import { GetIndicateursValeursResponseType } from '../models/get-indicateurs.response'; import { + IndicateurDefinition, IndicateurDefinitionAvecEnfantsType, + IndicateurDefinitionEssential, indicateurDefinitionTable, - IndicateurDefinitionType, - MinimalIndicateurDefinitionType, } from '../models/indicateur-definition.table'; import { indicateurGroupeTable } from '../models/indicateur-groupe.table'; import { indicateurSourceMetadonneeTable, - IndicateurSourceMetadonneeType, + SourceMetadonnee, } from '../models/indicateur-source-metadonnee.table'; import { - CreateIndicateurValeurType, - IndicateurAvecValeursParSource, - IndicateurAvecValeursType, + IndicateurAvecValeurs, + indicateurAvecValeursParSourceSchema, + IndicateurValeur, IndicateurValeurAvecMetadonnesDefinition, - IndicateurValeurGroupee, - IndicateurValeursGroupeeParSource, + indicateurValeurGroupeeSchema, + IndicateurValeurInsert, + indicateurValeursGroupeeParSourceSchema, indicateurValeurTable, - IndicateurValeurType, } from '../models/indicateur-valeur.table'; +export class IndicateurValeurGroupee extends createZodDto( + extendApi(indicateurValeurGroupeeSchema) +) {} + +export class IndicateurValeursGroupeeParSource extends createZodDto( + extendApi(indicateurValeursGroupeeParSourceSchema) +) {} + +export class IndicateurAvecValeursParSource extends createZodDto( + extendApi(indicateurAvecValeursParSourceSchema) +) {} + @Injectable() export default class IndicateursService { private readonly logger = new Logger(IndicateursService.name); @@ -213,9 +227,8 @@ export default class IndicateursService { const indicateurValeursSeules = indicateurValeurs.map( (v) => v.indicateur_valeur ); - const initialDefinitionsAcc: { [key: string]: IndicateurDefinitionType } = - {}; - let uniqueIndicateurDefinitions: IndicateurDefinitionType[]; + const initialDefinitionsAcc: { [key: string]: IndicateurDefinition } = {}; + let uniqueIndicateurDefinitions: IndicateurDefinition[]; if (!options.identifiantsReferentiel?.length) { uniqueIndicateurDefinitions = Object.values( indicateurValeurs.reduce((acc, v) => { @@ -225,7 +238,7 @@ export default class IndicateursService { } return acc; }, initialDefinitionsAcc) - ) as IndicateurDefinitionType[]; + ) as IndicateurDefinition[]; } else { uniqueIndicateurDefinitions = await this.getReferentielIndicateurDefinitions( @@ -258,7 +271,7 @@ export default class IndicateursService { }); const initialMetadonneesAcc: { - [key: string]: IndicateurSourceMetadonneeType; + [key: string]: SourceMetadonnee; } = {}; const uniqueIndicateurMetadonnees = Object.values( indicateurValeurs.reduce((acc, v) => { @@ -268,7 +281,7 @@ export default class IndicateursService { } return acc; }, initialMetadonneesAcc) - ) as IndicateurSourceMetadonneeType[]; + ) as SourceMetadonnee[]; const indicateurValeurGroupeesParSource = this.groupeIndicateursValeursParIndicateurEtSource( @@ -352,12 +365,12 @@ export default class IndicateursService { this.logger.log(`${definitions.length} définitions trouvées`); return definitions.map( - (def: IndicateurDefinitionType & { enfants: unknown[] }) => { + (def: IndicateurDefinition & { enfants: unknown[] }) => { const enfants = def.enfants?.filter(Boolean); return { ...def, enfants: enfants?.length - ? (objectToCamel(enfants) as IndicateurDefinitionType[]) + ? (objectToCamel(enfants) as IndicateurDefinition[]) : null, }; } @@ -365,9 +378,9 @@ export default class IndicateursService { } async upsertIndicateurValeurs( - indicateurValeurs: CreateIndicateurValeurType[], + indicateurValeurs: IndicateurValeurInsert[], tokenInfo: AuthenticatedUser - ): Promise { + ): Promise { if (tokenInfo) { const collectiviteIds = [ ...new Set(indicateurValeurs.map((v) => v.collectiviteId)), @@ -396,7 +409,7 @@ export default class IndicateursService { const [indicateurValeursAvecMetadonnees, indicateurValeursSansMetadonnees] = partition(indicateurValeurs, (v) => Boolean(v.metadonneeId)); - const indicateurValeursResultat: IndicateurValeurType[] = []; + const indicateurValeursResultat: IndicateurValeur[] = []; if (indicateurValeursAvecMetadonnees.length) { this.logger.log( `Upsert des ${ @@ -532,17 +545,17 @@ export default class IndicateursService { } groupeIndicateursValeursParIndicateur( - indicateurValeurs: IndicateurValeurType[], - indicateurDefinitions: IndicateurDefinitionType[], + indicateurValeurs: IndicateurValeur[], + indicateurDefinitions: IndicateurDefinition[], commentairesNonInclus = false - ): IndicateurAvecValeursType[] { + ): IndicateurAvecValeurs[] { const initialDefinitionsAcc: { - [key: string]: MinimalIndicateurDefinitionType; + [key: string]: IndicateurDefinitionEssential; } = {}; const uniqueIndicateurDefinitions = Object.values( indicateurDefinitions.reduce((acc, def) => { if (def?.id) { - const minimaleIndicateurDefinition = _.pick( + const minimaleIndicateurDefinition = _.pick( def, [ 'id', @@ -554,12 +567,12 @@ export default class IndicateursService { 'borneMin', 'borneMax', ] - ) as MinimalIndicateurDefinitionType; + ) as IndicateurDefinitionEssential; acc[def.id.toString()] = minimaleIndicateurDefinition; } return acc; }, initialDefinitionsAcc) - ) as IndicateurDefinitionType[]; + ) as IndicateurDefinition[]; const indicateurAvecValeurs = uniqueIndicateurDefinitions.map( (indicateurDefinition) => { @@ -588,7 +601,7 @@ export default class IndicateursService { valeurs.sort((a, b) => { return a.dateValeur.localeCompare(b.dateValeur); }); - const indicateurAvecValeurs: IndicateurAvecValeursType = { + const indicateurAvecValeurs: IndicateurAvecValeurs = { definition: indicateurDefinition, valeurs, }; @@ -599,13 +612,12 @@ export default class IndicateursService { } groupeIndicateursValeursParIndicateurEtSource( - indicateurValeurs: IndicateurValeurType[], - indicateurDefinitions: IndicateurDefinitionType[], - indicateurMetadonnees: IndicateurSourceMetadonneeType[], + indicateurValeurs: IndicateurValeur[], + indicateurDefinitions: IndicateurDefinition[], + indicateurMetadonnees: SourceMetadonnee[], supprimeIndicateursSansValeurs = true ): IndicateurAvecValeursParSource[] { - const initialDefinitionsAcc: { [key: string]: IndicateurDefinitionType } = - {}; + const initialDefinitionsAcc: { [key: string]: IndicateurDefinition } = {}; const uniqueIndicateurDefinitions = Object.values( indicateurDefinitions.reduce((acc, def) => { if (def?.id) { @@ -613,7 +625,7 @@ export default class IndicateursService { } return acc; }, initialDefinitionsAcc) - ) as IndicateurDefinitionType[]; + ) as IndicateurDefinition[]; const indicateurAvecValeurs = uniqueIndicateurDefinitions.map( (indicateurDefinition) => { @@ -637,7 +649,7 @@ export default class IndicateursService { const metadonneesUtilisees: Record< string, - Record + Record > = {}; const valeursParSource = groupBy(valeurs, (valeur) => { if (!valeur.metadonneeId) { diff --git a/backend/src/indicateurs/services/trajectoires-data.service.spec.ts b/backend/src/indicateurs/services/trajectoires-data.service.spec.ts index 680bd7f23f..c19e863f59 100644 --- a/backend/src/indicateurs/services/trajectoires-data.service.spec.ts +++ b/backend/src/indicateurs/services/trajectoires-data.service.spec.ts @@ -1,12 +1,11 @@ +import { PermissionService } from '@/backend/auth/authorizations/permission.service'; import { Test } from '@nestjs/testing'; -import { DateTime } from 'luxon'; import CollectivitesService from '../../collectivites/services/collectivites.service'; import SheetService from '../../utils/google-sheets/sheet.service'; -import { IndicateurValeurType } from '../models/indicateur-valeur.table'; +import { IndicateurValeur } from '../models/indicateur-valeur.table'; import IndicateurSourcesService from './indicateur-sources.service'; import IndicateursService from './indicateurs.service'; import TrajectoiresDataService from './trajectoires-data.service'; -import { PermissionService } from '@/backend/auth/authorizations/permission.service'; describe('TrajectoiresDataService test', () => { let trajectoiresDataService: TrajectoiresDataService; @@ -37,7 +36,7 @@ describe('TrajectoiresDataService test', () => { describe('getInterpolationValeur', () => { it('Interpolation possible, cas de valeurs égales', async () => { - const indicateurValeurs: IndicateurValeurType[] = [ + const indicateurValeurs: IndicateurValeur[] = [ { id: 640644, collectiviteId: 3894, @@ -120,7 +119,7 @@ describe('TrajectoiresDataService test', () => { }); it('Interpolation possible, cas de valeurs égales', async () => { - const indicateurValeurs: IndicateurValeurType[] = [ + const indicateurValeurs: IndicateurValeur[] = [ { id: 651923, collectiviteId: 3903, @@ -189,7 +188,7 @@ describe('TrajectoiresDataService test', () => { describe('getClosestValeur', () => { it('Cas standard', async () => { - const indicateurValeurs: IndicateurValeurType[] = [ + const indicateurValeurs: IndicateurValeur[] = [ { id: 640644, collectiviteId: 3894, diff --git a/backend/src/indicateurs/services/trajectoires-data.service.ts b/backend/src/indicateurs/services/trajectoires-data.service.ts index 3ceebef346..7f842e22ed 100644 --- a/backend/src/indicateurs/services/trajectoires-data.service.ts +++ b/backend/src/indicateurs/services/trajectoires-data.service.ts @@ -16,13 +16,13 @@ import { DonneesARemplirResultType } from '../models/donnees-a-remplir-result.dt import { DonneesARemplirValeurType } from '../models/donnees-a-remplir-valeur.dto'; import { DonneesCalculTrajectoireARemplirType } from '../models/donnees-calcul-trajectoire-a-remplir.dto'; import { - CreateIndicateurSourceMetadonneeType, - IndicateurSourceMetadonneeType, + SourceMetadonnee, + SourceMetadonneeInsert, } from '../models/indicateur-source-metadonnee.table'; -import { CreateIndicateurSourceType } from '../models/indicateur-source.table'; +import { SourceInsert } from '../models/indicateur-source.table'; import { + IndicateurValeur, IndicateurValeurAvecMetadonnesDefinition, - IndicateurValeurType, } from '../models/indicateur-valeur.table'; import { VerificationTrajectoireRequestType } from '../models/verification-trajectoire.request'; import { @@ -48,22 +48,21 @@ export default class TrajectoiresDataService { public readonly TEST_COLLECTIVITE_VALID_SIREN = '242900314'; - public readonly SNBC_SOURCE: CreateIndicateurSourceType = { + public readonly SNBC_SOURCE: SourceInsert = { id: 'snbc', libelle: 'SNBC', }; - public readonly SNBC_SOURCE_METADONNEES: CreateIndicateurSourceMetadonneeType = - { - sourceId: this.SNBC_SOURCE.id, - dateVersion: DateTime.fromISO('2024-07-11T00:00:00', { - zone: 'utc', - }).toISO() as string, - nomDonnees: 'SNBC', - diffuseur: 'ADEME', - producteur: 'ADEME', - // methodologie: '', - // limites: '', - }; + public readonly SNBC_SOURCE_METADONNEES: SourceMetadonneeInsert = { + sourceId: this.SNBC_SOURCE.id, + dateVersion: DateTime.fromISO('2024-07-11T00:00:00', { + zone: 'utc', + }).toISO() as string, + nomDonnees: 'SNBC', + diffuseur: 'ADEME', + producteur: 'ADEME', + // methodologie: '', + // limites: '', + }; public readonly SNBC_DATE_REFERENCE = '2015-01-01'; public readonly SNBC_SIREN_CELLULE = 'Caract_territoire!F6'; @@ -203,8 +202,7 @@ export default class TrajectoiresDataService { 'cae_2.a', // 297 Total ]; - private indicateurSourceMetadonnee: IndicateurSourceMetadonneeType | null = - null; + private indicateurSourceMetadonnee: SourceMetadonnee | null = null; constructor( private readonly collectivitesService: CollectivitesService, @@ -213,7 +211,7 @@ export default class TrajectoiresDataService { private readonly permissionService: PermissionService ) {} - async getTrajectoireIndicateursMetadonnees(): Promise { + async getTrajectoireIndicateursMetadonnees(): Promise { if (!this.indicateurSourceMetadonnee) { // Création de la source métadonnée SNBC si elle n'existe pas this.indicateurSourceMetadonnee = @@ -503,7 +501,7 @@ export default class TrajectoiresDataService { }; } - getClosestValeur(indicateurValeurs: IndicateurValeurType[]): { + getClosestValeur(indicateurValeurs: IndicateurValeur[]): { valeur: number | null; date_min: string | null; date_max: string | null; @@ -533,7 +531,7 @@ export default class TrajectoiresDataService { }; } - getInterpolationValeur(indicateurValeurs: IndicateurValeurType[]): { + getInterpolationValeur(indicateurValeurs: IndicateurValeur[]): { valeur: number | null; date_min: string | null; date_max: string | null; diff --git a/backend/src/indicateurs/services/trajectoires-spreadsheet.service.ts b/backend/src/indicateurs/services/trajectoires-spreadsheet.service.ts index fae81d1e33..e12ee432d2 100644 --- a/backend/src/indicateurs/services/trajectoires-spreadsheet.service.ts +++ b/backend/src/indicateurs/services/trajectoires-spreadsheet.service.ts @@ -17,10 +17,10 @@ import { CalculTrajectoireReset, CalculTrajectoireResultatMode, } from '../models/calcul-trajectoire.request'; -import { CalculTrajectoireResultType } from '../models/calcul-trajectoire.response'; +import { CalculTrajectoireResult } from '../models/calcul-trajectoire.response'; import { DonneesCalculTrajectoireARemplirType } from '../models/donnees-calcul-trajectoire-a-remplir.dto'; -import { IndicateurDefinitionType } from '../models/indicateur-definition.table'; -import { CreateIndicateurValeurType } from '../models/indicateur-valeur.table'; +import { IndicateurDefinition } from '../models/indicateur-definition.table'; +import { IndicateurValeurInsert } from '../models/indicateur-valeur.table'; import { VerificationTrajectoireStatus } from '../models/verification-trajectoire.response'; import IndicateurSourcesService from './indicateur-sources.service'; import IndicateursService from './indicateurs.service'; @@ -59,7 +59,7 @@ export default class TrajectoiresSpreadsheetService { request: CalculTrajectoireRequestType, tokenInfo: AuthenticatedUser, epci?: EpciType - ): Promise { + ): Promise { let mode: CalculTrajectoireResultatMode = CalculTrajectoireResultatMode.NOUVEAU_SPREADSHEET; @@ -167,7 +167,7 @@ export default class TrajectoiresSpreadsheetService { ); mode = CalculTrajectoireResultatMode.DONNEES_EN_BDD; - const result: CalculTrajectoireResultType = { + const result: CalculTrajectoireResult = { mode: mode, sourcesDonneesEntree: resultatVerification.sourcesDonneesEntree || [], indentifiantsReferentielManquantsDonneesEntree: @@ -374,7 +374,7 @@ export default class TrajectoiresSpreadsheetService { true ); - const result: CalculTrajectoireResultType = { + const result: CalculTrajectoireResult = { mode: mode, sourcesDonneesEntree: resultatVerification.donneesEntree!.sources, indentifiantsReferentielManquantsDonneesEntree: [ @@ -397,7 +397,7 @@ export default class TrajectoiresSpreadsheetService { return result; } - inverseSigneSequestrations(result: CalculTrajectoireResultType) { + inverseSigneSequestrations(result: CalculTrajectoireResult) { // Il y a le cae_1.csc qui est une exception result.trajectoire.emissionsGes.forEach((emissionGes) => { if ( @@ -471,9 +471,9 @@ export default class TrajectoiresSpreadsheetService { indicateurSourceMetadonneeId: number, donneesSpreadsheet: any[][] | null, identifiantsReferentielAssocie: string[], - indicateurResultatDefinitions: IndicateurDefinitionType[], + indicateurResultatDefinitions: IndicateurDefinition[], donneesCalculTrajectoire: DonneesCalculTrajectoireARemplirType - ): CreateIndicateurValeurType[] { + ): IndicateurValeurInsert[] { const donneesEntree = [ ...donneesCalculTrajectoire.emissionsGes.valeurs, ...donneesCalculTrajectoire.consommationsFinales.valeurs, @@ -484,7 +484,7 @@ export default class TrajectoiresSpreadsheetService { donneesCalculTrajectoire ); - const indicateurValeursResultat: CreateIndicateurValeurType[] = []; + const indicateurValeursResultat: IndicateurValeurInsert[] = []; donneesSpreadsheet?.forEach((ligne, ligneIndex) => { const identifiantReferentielSortie = identifiantsReferentielAssocie[ligneIndex]; @@ -587,7 +587,7 @@ export default class TrajectoiresSpreadsheetService { // Les valeurs de séquestration sont positives en base quand il y a une séquestration mais la convention inverse est dans l'excel facteur = -1; } - const indicateurValeur: CreateIndicateurValeurType = { + const indicateurValeur: IndicateurValeurInsert = { indicateurId: indicateurResultatDefinition.id, collectiviteId: collectiviteId, metadonneeId: indicateurSourceMetadonneeId, diff --git a/backend/src/indicateurs/shared/fixtures/trajectoire-snbc-calcul-retour.ts b/backend/src/indicateurs/shared/fixtures/trajectoire-snbc-calcul-retour.ts index d84b966a7f..1cb7bb3879 100644 --- a/backend/src/indicateurs/shared/fixtures/trajectoire-snbc-calcul-retour.ts +++ b/backend/src/indicateurs/shared/fixtures/trajectoire-snbc-calcul-retour.ts @@ -1,7 +1,7 @@ import { CalculTrajectoireResultatMode } from '../../models/calcul-trajectoire.request'; -import { CalculTrajectoireResponseType } from '../../models/calcul-trajectoire.response'; +import { CalculTrajectoireResponse } from '../../models/calcul-trajectoire.response'; -export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { +export const trajectoireSnbcCalculRetour: CalculTrajectoireResponse = { mode: CalculTrajectoireResultatMode.MAJ_SPREADSHEET_EXISTANT, sourcesDonneesEntree: ['rare'], indentifiantsReferentielManquantsDonneesEntree: [ diff --git a/backend/src/personnalisations/models/get-personnalisation-consequences.request.ts b/backend/src/personnalisations/models/get-personnalisation-consequences.request.ts index aec63f8a5f..c8597739b2 100644 --- a/backend/src/personnalisations/models/get-personnalisation-consequences.request.ts +++ b/backend/src/personnalisations/models/get-personnalisation-consequences.request.ts @@ -1,11 +1,11 @@ import { extendApi } from '@anatine/zod-openapi'; import { z } from 'zod'; -import { ReferentielType } from '../../referentiels/models/referentiel.enum'; +import { referentielIdEnumSchema } from '../../referentiels/models/referentiel.enum'; import { getPersonnalisationReponsesRequestSchema } from './get-personnalisation-reponses.request'; export const getPersonnalisationConsequencesRequestSchema = extendApi( getPersonnalisationReponsesRequestSchema.extend({ - referentiel: z.nativeEnum(ReferentielType).optional(), + referentiel: referentielIdEnumSchema.optional(), }) ).describe( 'Paramètres de la requête pour obtenir les conséquences de personnalisation sur un référentiel pour une collectivité donnée' diff --git a/backend/src/personnalisations/models/get-personnalisation-regles.request.ts b/backend/src/personnalisations/models/get-personnalisation-regles.request.ts index 8d01fd3303..becb38e95a 100644 --- a/backend/src/personnalisations/models/get-personnalisation-regles.request.ts +++ b/backend/src/personnalisations/models/get-personnalisation-regles.request.ts @@ -1,10 +1,10 @@ import { extendApi } from '@anatine/zod-openapi'; import { z } from 'zod'; -import { ReferentielType } from '../../referentiels/models/referentiel.enum'; +import { referentielIdEnumSchema } from '../../referentiels/models/referentiel.enum'; export const getPersonnalisationReglesRequestSchema = extendApi( z.object({ - referentiel: z.nativeEnum(ReferentielType).optional(), + referentiel: referentielIdEnumSchema.optional(), }) ).describe( 'Paramètres de la requête pour obtenir les règles de personnalisation' diff --git a/backend/src/referentiels/compute-score/compute-score.router.ts b/backend/src/referentiels/compute-score/compute-score.router.ts index 8f50b4ed8f..3ee7996f6b 100644 --- a/backend/src/referentiels/compute-score/compute-score.router.ts +++ b/backend/src/referentiels/compute-score/compute-score.router.ts @@ -1,12 +1,12 @@ +import { TrpcService } from '@/backend/utils/trpc/trpc.service'; import { Injectable } from '@nestjs/common'; import z from 'zod'; -import { TrpcService } from '@/backend/utils/trpc/trpc.service'; import { getReferentielScoresRequestSchema } from '../models/get-referentiel-scores.request'; -import { ReferentielType } from '../models/referentiel.enum'; +import { referentielIdEnumSchema } from '../models/referentiel.enum'; import ReferentielsScoringService from '../services/referentiels-scoring.service'; export const computeScoreRequestSchema = z.object({ - referentielId: z.nativeEnum(ReferentielType), + referentielId: referentielIdEnumSchema, collectiviteId: z.number().int(), parameters: getReferentielScoresRequestSchema, }); diff --git a/backend/src/referentiels/controllers/referentiels-scoring.controller.ts b/backend/src/referentiels/controllers/referentiels-scoring.controller.ts index aee1f87d21..b06b72752e 100644 --- a/backend/src/referentiels/controllers/referentiels-scoring.controller.ts +++ b/backend/src/referentiels/controllers/referentiels-scoring.controller.ts @@ -25,7 +25,7 @@ import { getReferentielScoresRequestSchema } from '../models/get-referentiel-sco import { getReferentielScoresResponseSchema } from '../models/get-referentiel-scores.response'; import { getScoreSnapshotsRequestSchema } from '../models/get-score-snapshots.request'; import { getScoreSnapshotsResponseSchema } from '../models/get-score-snapshots.response'; -import { ReferentielType } from '../models/referentiel.enum'; +import { ReferentielId } from '../models/referentiel.enum'; import ReferentielsScoringSnapshotsService from '../services/referentiels-scoring-snapshots.service'; import ReferentielsScoringService from '../services/referentiels-scoring.service'; @@ -81,7 +81,7 @@ export class ReferentielsScoringController { @ApiResponse({ type: GetActionStatutsResponseClass }) async getReferentielStatuts( @Param('collectivite_id') collectiviteId: number, - @Param('referentiel_id') referentielId: ReferentielType, + @Param('referentiel_id') referentielId: ReferentielId, @Query() parameters: GetActionStatutsRequestClass, @TokenInfo() tokenInfo: AuthenticatedUser ): Promise { @@ -97,7 +97,7 @@ export class ReferentielsScoringController { @Get('referentiels/:referentiel_id/scores') @ApiResponse({ type: GetReferentielMultipleScoresResponseClass }) async getReferentielMultipleScorings( - @Param('referentiel_id') referentielId: ReferentielType, + @Param('referentiel_id') referentielId: ReferentielId, @Query() parameters: GetReferentielMultipleScoresRequestClass, @TokenInfo() tokenInfo: AuthenticatedUser ): Promise { @@ -113,7 +113,7 @@ export class ReferentielsScoringController { @ApiResponse({ type: GetReferentielScoresResponseClass }) async getReferentielScoring( @Param('collectivite_id') collectiviteId: number, - @Param('referentiel_id') referentielId: ReferentielType, + @Param('referentiel_id') referentielId: ReferentielId, @Query() parameters: GetReferentielScoresRequestClass, @TokenInfo() tokenInfo: AuthenticatedUser ): Promise { @@ -132,7 +132,7 @@ export class ReferentielsScoringController { ) async checkReferentielScore( @Param('collectivite_id') collectiviteId: number, - @Param('referentiel_id') referentielId: ReferentielType, + @Param('referentiel_id') referentielId: ReferentielId, @Query() parameters: CheckReferentielScoresRequestType, @Req() req: Request ): Promise { @@ -151,7 +151,7 @@ export class ReferentielsScoringController { ) async listSummary( @Param('collectivite_id') collectiviteId: number, - @Param('referentiel_id') referentielId: ReferentielType, + @Param('referentiel_id') referentielId: ReferentielId, @Query() parameters: GetScoreSnapshotsRequestClass, @TokenInfo() tokenInfo: AuthUser ): Promise { @@ -168,7 +168,7 @@ export class ReferentielsScoringController { ) async getReferentielScoreSnapshot( @Param('collectivite_id') collectiviteId: number, - @Param('referentiel_id') referentielId: ReferentielType, + @Param('referentiel_id') referentielId: ReferentielId, @Param('snapshot_ref') snapshotRef: string, @TokenInfo() tokenInfo: AuthenticatedUser ) { @@ -194,7 +194,7 @@ export class ReferentielsScoringController { ) async deleteReferentielScoreSnapshot( @Param('collectivite_id') collectiviteId: number, - @Param('referentiel_id') referentielId: ReferentielType, + @Param('referentiel_id') referentielId: ReferentielId, @Param('snapshot_ref') snapshotRef: string, @TokenInfo() tokenInfo: AuthUser ): Promise { diff --git a/backend/src/referentiels/controllers/referentiels-scoring.e2e-spec.ts b/backend/src/referentiels/controllers/referentiels-scoring.e2e-spec.ts index 431f7fe40a..ed1a939997 100644 --- a/backend/src/referentiels/controllers/referentiels-scoring.e2e-spec.ts +++ b/backend/src/referentiels/controllers/referentiels-scoring.e2e-spec.ts @@ -4,6 +4,7 @@ import { getTestApp } from '../../../test/app-utils'; import { getAuthToken } from '../../../test/auth-utils'; import { getCollectiviteIdBySiren } from '../../../test/collectivites-utils'; import { HttpErrorResponse } from '../../utils/nest/http-error.response'; +import { referentielIdEnumSchema } from '../index-domain'; import { ActionScoreType } from '../models/action-score.dto'; import { ActionStatutType } from '../models/action-statut.table'; import { ActionType } from '../models/action-type.enum'; @@ -12,7 +13,6 @@ import { GetReferentielScoresResponseType } from '../models/get-referentiel-scor import { GetScoreSnapshotsResponseType } from '../models/get-score-snapshots.response'; import { HistoriqueActionStatutType } from '../models/historique-action-statut.table'; import { ReferentielActionWithScoreType } from '../models/referentiel-action-avec-score.dto'; -import { ReferentielType } from '../models/referentiel.enum'; import { ScoreJalon } from '../models/score-jalon.enum'; describe('Referentiels scoring routes', () => { @@ -245,7 +245,7 @@ describe('Referentiels scoring routes', () => { .expect(200); const expectedCurrentSnapshotList: GetScoreSnapshotsResponseType = { collectiviteId: 1, - referentielId: ReferentielType.CAE, + referentielId: referentielIdEnumSchema.enum.cae, typesJalon: [ScoreJalon.SCORE_COURANT], snapshots: [ { @@ -297,7 +297,7 @@ describe('Referentiels scoring routes', () => { .expect(200); const expectedSnapshotList: GetScoreSnapshotsResponseType = { collectiviteId: 1, - referentielId: ReferentielType.CAE, + referentielId: referentielIdEnumSchema.enum.cae, typesJalon: [ScoreJalon.DATE_PERSONNALISEE], snapshots: [ { diff --git a/backend/src/referentiels/controllers/referentiels.controller.ts b/backend/src/referentiels/controllers/referentiels.controller.ts index e21b60166b..ee47ddf70c 100644 --- a/backend/src/referentiels/controllers/referentiels.controller.ts +++ b/backend/src/referentiels/controllers/referentiels.controller.ts @@ -6,7 +6,7 @@ import { AllowPublicAccess } from '../../auth/decorators/allow-public-access.dec import { TokenInfo } from '../../auth/decorators/token-info.decorators'; import { AuthenticatedUser } from '../../auth/models/auth.models'; import { getReferentielResponseSchema } from '../models/get-referentiel.response'; -import { ReferentielType } from '../models/referentiel.enum'; +import { ReferentielId } from '../models/referentiel.enum'; import ReferentielsService from '../services/referentiels.service'; class GetReferentielResponseClass extends createZodDto( @@ -24,7 +24,7 @@ export class ReferentielsController { @Get(':referentiel_id') @ApiResponse({ type: GetReferentielResponseClass }) async getReferentiel( - @Param('referentiel_id') referentielId: ReferentielType, + @Param('referentiel_id') referentielId: ReferentielId, @TokenInfo() tokenInfo: AuthenticatedUser ): Promise { return this.referentielsService.getReferentiel(referentielId, true); @@ -34,7 +34,7 @@ export class ReferentielsController { @Get(':referentiel_id/import') @ApiResponse({ type: GetReferentielResponseClass }) async importReferentiel( - @Param('referentiel_id') referentielId: ReferentielType, + @Param('referentiel_id') referentielId: ReferentielId, @TokenInfo() tokenInfo: AuthenticatedUser ): Promise { return this.referentielsService.importReferentiel(referentielId); diff --git a/backend/src/referentiels/models/action-definition.table.ts b/backend/src/referentiels/models/action-definition.table.ts index 1199cb1677..6c7b334f0b 100644 --- a/backend/src/referentiels/models/action-definition.table.ts +++ b/backend/src/referentiels/models/action-definition.table.ts @@ -12,7 +12,7 @@ import { z } from 'zod'; import { actionRelationTable } from './action-relation.table'; import { ActionType } from './action-type.enum'; import { referentielDefinitionTable } from './referentiel-definition.table'; -import { referentielEnum } from './referentiel.enum'; +import { referentielIdPgEnum } from './referentiel.enum'; export enum ActionCategoryType { BASES = 'bases', @@ -32,7 +32,7 @@ export const actionIdReference = actionIdVarchar.references( export const actionDefinitionTable = pgTable('action_definition', { modifiedAt, actionId: actionIdVarchar.primaryKey().notNull(), - referentiel: referentielEnum('referentiel').notNull(), + referentiel: referentielIdPgEnum('referentiel').notNull(), referentielId: varchar('referentiel_id', { length: 30 }) .notNull() .references(() => referentielDefinitionTable.id), diff --git a/backend/src/referentiels/models/action-relation.table.ts b/backend/src/referentiels/models/action-relation.table.ts index 3f3f18d376..74fa107e50 100644 --- a/backend/src/referentiels/models/action-relation.table.ts +++ b/backend/src/referentiels/models/action-relation.table.ts @@ -2,14 +2,14 @@ import { InferInsertModel, InferSelectModel } from 'drizzle-orm'; import { pgTable, varchar } from 'drizzle-orm/pg-core'; import { createInsertSchema, createSelectSchema } from 'drizzle-zod'; import { actionDefinitionTable } from './action-definition.table'; -import { referentielEnum } from './referentiel.enum'; +import { referentielIdPgEnum } from './referentiel.enum'; export const actionRelationTable = pgTable('action_relation', { id: varchar('id', { length: 30 }) .references(() => actionDefinitionTable.actionId) .primaryKey() .notNull(), - referentiel: referentielEnum('referentiel').notNull(), + referentiel: referentielIdPgEnum('referentiel').notNull(), parent: varchar('parent', { length: 30 }).references( () => actionDefinitionTable.actionId ), diff --git a/backend/src/referentiels/models/client-scores.table.ts b/backend/src/referentiels/models/client-scores.table.ts index 31dbf20a28..af1ddf1104 100644 --- a/backend/src/referentiels/models/client-scores.table.ts +++ b/backend/src/referentiels/models/client-scores.table.ts @@ -9,13 +9,13 @@ import { } from 'drizzle-orm/pg-core'; import { createInsertSchema, createSelectSchema } from 'drizzle-zod'; import { collectiviteTable } from '../../collectivites/shared/models/collectivite.table'; -import { referentielEnum } from './referentiel.enum'; +import { referentielIdPgEnum } from './referentiel.enum'; export const clientScoresTable = pgTable( 'client_scores', { collectiviteId: integer('collectivite_id').notNull(), - referentiel: referentielEnum('referentiel').notNull(), // TODO: Reference referentiel table + referentiel: referentielIdPgEnum('referentiel').notNull(), // TODO: Reference referentiel table scores: jsonb('scores').notNull(), modifiedAt: timestamp('modified_at', { withTimezone: true, diff --git a/backend/src/referentiels/models/get-check-scores.response.ts b/backend/src/referentiels/models/get-check-scores.response.ts index c9110e2145..6f16fe3555 100644 --- a/backend/src/referentiels/models/get-check-scores.response.ts +++ b/backend/src/referentiels/models/get-check-scores.response.ts @@ -2,12 +2,12 @@ import { extendApi } from '@anatine/zod-openapi'; import { z } from 'zod'; import { actionScoreSchema } from './action-score.dto'; import { CheckScoreStatus } from './check-score-status.enum'; -import { ReferentielType } from './referentiel.enum'; +import { referentielIdEnumSchema } from './referentiel.enum'; export const getCheckScoresResponseSchema = extendApi( z.object({ collectiviteId: z.number(), - referentielId: z.nativeEnum(ReferentielType), + referentielId: referentielIdEnumSchema, date: z.string().datetime(), verification_status: z.nativeEnum(CheckScoreStatus), differences: z.record( diff --git a/backend/src/referentiels/models/get-referentiel-scores.response.ts b/backend/src/referentiels/models/get-referentiel-scores.response.ts index e71e5d8a48..2ff6ba0b16 100644 --- a/backend/src/referentiels/models/get-referentiel-scores.response.ts +++ b/backend/src/referentiels/models/get-referentiel-scores.response.ts @@ -3,7 +3,7 @@ import { z } from 'zod'; import { collectiviteAvecTypeSchema } from '../../collectivites/identite-collectivite.dto'; import { ComputeScoreMode } from './compute-scores-mode.enum'; import { referentielActionAvecScoreDtoSchema } from './referentiel-action-avec-score.dto'; -import { ReferentielType } from './referentiel.enum'; +import { referentielIdEnumSchema } from './referentiel.enum'; import { ScoreJalon } from './score-jalon.enum'; export const getReferentielScoresResponseSnapshotInfoSchema = z.object({ @@ -18,7 +18,7 @@ export const getReferentielScoresResponseSnapshotInfoSchema = z.object({ export const getReferentielScoresResponseSchema = extendApi( z.object({ collectiviteId: z.number(), - referentielId: z.nativeEnum(ReferentielType), + referentielId: referentielIdEnumSchema, referentielVersion: z.string(), collectiviteInfo: collectiviteAvecTypeSchema, date: z.string().datetime(), diff --git a/backend/src/referentiels/models/get-score-snapshots.response.ts b/backend/src/referentiels/models/get-score-snapshots.response.ts index 451bd501e4..5b0f8da149 100644 --- a/backend/src/referentiels/models/get-score-snapshots.response.ts +++ b/backend/src/referentiels/models/get-score-snapshots.response.ts @@ -1,6 +1,6 @@ import { extendApi } from '@anatine/zod-openapi'; import z from 'zod'; -import { ReferentielType } from './referentiel.enum'; +import { referentielIdEnumSchema } from './referentiel.enum'; import { ScoreJalon } from './score-jalon.enum'; import { scoreSnapshotSchema } from './score-snapshot.table'; @@ -49,7 +49,7 @@ export type ScoreSnapshotCollectiviteInfoType = z.infer< export const getScoreSnapshotsResponseSchema = extendApi( z.object({ collectiviteId: z.number(), - referentielId: z.nativeEnum(ReferentielType), + referentielId: referentielIdEnumSchema, typesJalon: z.nativeEnum(ScoreJalon).array(), snapshots: scoreSnapshotInfo.array(), }) diff --git a/backend/src/referentiels/models/labellisation-audit.table.ts b/backend/src/referentiels/models/labellisation-audit.table.ts index 039a59a572..b36b6ad7ed 100644 --- a/backend/src/referentiels/models/labellisation-audit.table.ts +++ b/backend/src/referentiels/models/labellisation-audit.table.ts @@ -12,7 +12,7 @@ import { createInsertSchema, createSelectSchema } from 'drizzle-zod'; import { collectiviteTable } from '../../collectivites/shared/models/collectivite.table'; import { labellisationDemandeTable } from './labellisation-demande.table'; import { labellisationSchema } from './labellisation.schema'; -import { referentielEnum } from './referentiel.enum'; +import { referentielIdPgEnum } from './referentiel.enum'; export const labellisationAuditTable = labellisationSchema.table( 'audit', @@ -20,7 +20,7 @@ export const labellisationAuditTable = labellisationSchema.table( id: serial('id').primaryKey().notNull(), collectiviteId: integer('collectivite_id').notNull(), // TODO: change later to use the referentiel definition table - referentiel: referentielEnum('referentiel').notNull(), + referentiel: referentielIdPgEnum('referentiel').notNull(), demandeId: integer('demande_id'), dateDebut: timestamp('date_debut', TIMESTAMP_OPTIONS), dateFin: timestamp('date_fin', TIMESTAMP_OPTIONS), diff --git a/backend/src/referentiels/models/labellisation-demande.table.ts b/backend/src/referentiels/models/labellisation-demande.table.ts index bfa1098ade..861d0e8a5f 100644 --- a/backend/src/referentiels/models/labellisation-demande.table.ts +++ b/backend/src/referentiels/models/labellisation-demande.table.ts @@ -11,7 +11,7 @@ import { authUsersTable } from '../../auth/models/auth-users.table'; import { collectiviteTable } from '../../collectivites/shared/models/collectivite.table'; import { labellisationEtoileEnum } from './labellisation-etoile.table'; import { labellisationSchema } from './labellisation.schema'; -import { referentielEnum } from './referentiel.enum'; +import { referentielIdPgEnum } from './referentiel.enum'; export enum LabellisationSujetDemandeEnumType { LABELLISATION = 'labellisation', @@ -35,7 +35,7 @@ export const labellisationDemandeTable = labellisationSchema.table( enCours: boolean('en_cours').default(true).notNull(), collectiviteId: integer('collectivite_id').notNull(), // TODO: change later to use the referentiel definition table - referentiel: referentielEnum('referentiel').notNull(), + referentiel: referentielIdPgEnum('referentiel').notNull(), etoiles: labellisationEtoileEnum('etoiles'), date: timestamp('date', TIMESTAMP_OPTIONS).defaultNow().notNull(), sujet: labellisationSujetDemandeEnum('sujet'), diff --git a/backend/src/referentiels/models/post-audit-scores.table.ts b/backend/src/referentiels/models/post-audit-scores.table.ts index f0c1d0d143..38e65087c6 100644 --- a/backend/src/referentiels/models/post-audit-scores.table.ts +++ b/backend/src/referentiels/models/post-audit-scores.table.ts @@ -9,13 +9,13 @@ import { } from 'drizzle-orm/pg-core'; import { createInsertSchema, createSelectSchema } from 'drizzle-zod'; import { labellisationAuditTable } from './labellisation-audit.table'; -import { referentielEnum } from './referentiel.enum'; +import { referentielIdPgEnum } from './referentiel.enum'; export const postAuditScoresTable = pgTable( 'post_audit_scores', { collectiviteId: integer('collectivite_id').notNull(), - referentiel: referentielEnum('referentiel').notNull(), + referentiel: referentielIdPgEnum('referentiel').notNull(), scores: jsonb('scores').notNull(), modifiedAt: timestamp('modified_at', { withTimezone: true, diff --git a/backend/src/referentiels/models/pre-audit-scores.table.ts b/backend/src/referentiels/models/pre-audit-scores.table.ts index ffd68be3b1..3c0a6b3fcb 100644 --- a/backend/src/referentiels/models/pre-audit-scores.table.ts +++ b/backend/src/referentiels/models/pre-audit-scores.table.ts @@ -9,13 +9,13 @@ import { } from 'drizzle-orm/pg-core'; import { createInsertSchema, createSelectSchema } from 'drizzle-zod'; import { labellisationAuditTable } from './labellisation-audit.table'; -import { referentielEnum } from './referentiel.enum'; +import { referentielIdPgEnum } from './referentiel.enum'; export const preAuditScoresTable = pgTable( 'pre_audit_scores', { collectiviteId: integer('collectivite_id').notNull(), - referentiel: referentielEnum('referentiel').notNull(), + referentiel: referentielIdPgEnum('referentiel').notNull(), scores: jsonb('scores').notNull(), modifiedAt: timestamp('modified_at', { withTimezone: true, diff --git a/backend/src/referentiels/models/referentiel.enum.ts b/backend/src/referentiels/models/referentiel.enum.ts index 6383f76bd0..88c42bb964 100644 --- a/backend/src/referentiels/models/referentiel.enum.ts +++ b/backend/src/referentiels/models/referentiel.enum.ts @@ -1,21 +1,21 @@ import { pgEnum } from 'drizzle-orm/pg-core'; import z from 'zod'; -export enum ReferentielType { - ECI = 'eci', - CAE = 'cae', - TE = 'te', - TE_TEST = 'te-test', -} -// WARNING: not using Object.values to use it with pgTable -export const referentielTypeEnumValues = [ - ReferentielType.CAE, - ReferentielType.ECI, - ReferentielType.TE, - ReferentielType.TE_TEST, -] as const; +// export enum ReferentielId { +// ECI = 'eci', +// CAE = 'cae', +// TE = 'te', +// TE_TEST = 'te-test', +// } -export const referentielTypeEnumSchema = z.enum(referentielTypeEnumValues); +export const referentielIdEnumValues = ['cae', 'eci', 'te', 'te-test'] as const; + +export const referentielIdEnumSchema = z.enum(referentielIdEnumValues); + +export type ReferentielId = z.infer; // Todo: to be removed -export const referentielEnum = pgEnum('referentiel', referentielTypeEnumValues); +export const referentielIdPgEnum = pgEnum( + 'referentiel', + referentielIdEnumValues +); diff --git a/backend/src/referentiels/services/labellisation.service.ts b/backend/src/referentiels/services/labellisation.service.ts index c2c7ac7385..e16b784899 100644 --- a/backend/src/referentiels/services/labellisation.service.ts +++ b/backend/src/referentiels/services/labellisation.service.ts @@ -9,7 +9,7 @@ import { labellisationEtoileMetaTable, LabellisationEtoileMetaType, } from '../models/labellisation-etoile.table'; -import { ReferentielType } from '../models/referentiel.enum'; +import { ReferentielId } from '../models/referentiel.enum'; import ReferentielsService from './referentiels.service'; @Injectable() @@ -34,7 +34,7 @@ export default class LabellisationService { async getAuditsForCollectivite( collectiviteId: number, - referentiel: ReferentielType, + referentiel: ReferentielId, onlyEnded = false ): Promise { const filter: (SQLWrapper | SQL)[] = [ diff --git a/backend/src/referentiels/services/referentiels-scoring-snapshots.service.ts b/backend/src/referentiels/services/referentiels-scoring-snapshots.service.ts index 296f0c3f2d..ecf36d0af5 100644 --- a/backend/src/referentiels/services/referentiels-scoring-snapshots.service.ts +++ b/backend/src/referentiels/services/referentiels-scoring-snapshots.service.ts @@ -24,7 +24,7 @@ import { ScoreSnapshotCollectiviteInfoType, ScoreSnapshotInfoType, } from '../models/get-score-snapshots.response'; -import { ReferentielType } from '../models/referentiel.enum'; +import { ReferentielId } from '../models/referentiel.enum'; import { ScoreJalon } from '../models/score-jalon.enum'; import { CreateScoreSnapshotType, @@ -304,7 +304,7 @@ export default class ReferentielsScoringSnapshotsService { if (snapshotForceUpdate) { const existingSnapshot = await this.getSummary( createScoreSnapshot.collectiviteId, - createScoreSnapshot.referentielId as ReferentielType, + createScoreSnapshot.referentielId as ReferentielId, createScoreSnapshot.ref!, true ); @@ -353,7 +353,7 @@ export default class ReferentielsScoringSnapshotsService { async listSummary( collectiviteId: number, - referentielId: ReferentielType, + referentielId: ReferentielId, { typesJalon }: GetScoreSnapshotsRequestType ): Promise { const result = await this.databaseService.db @@ -394,7 +394,7 @@ export default class ReferentielsScoringSnapshotsService { async getSummary( collectiviteId: number, - referentielId: ReferentielType, + referentielId: ReferentielId, snapshotRef: string, doNotThrowIfNotFound = false ): Promise { @@ -434,7 +434,7 @@ export default class ReferentielsScoringSnapshotsService { async get( collectiviteId: number, - referentielId: ReferentielType, + referentielId: ReferentielId, snapshotRef: string, doNotThrowIfNotFound?: boolean ): Promise { @@ -473,7 +473,7 @@ export default class ReferentielsScoringSnapshotsService { async delete( collectiviteId: number, - referentielId: ReferentielType, + referentielId: ReferentielId, snapshotRef: string, tokenInfo: AuthUser ): Promise { diff --git a/backend/src/referentiels/services/referentiels-scoring.service.ts b/backend/src/referentiels/services/referentiels-scoring.service.ts index b133e2ae5b..7db7b8f58b 100644 --- a/backend/src/referentiels/services/referentiels-scoring.service.ts +++ b/backend/src/referentiels/services/referentiels-scoring.service.ts @@ -74,7 +74,7 @@ import { preAuditScoresTable } from '../models/pre-audit-scores.table'; import { ReferentielActionWithScoreType } from '../models/referentiel-action-avec-score.dto'; import { ReferentielActionOrigineWithScoreType } from '../models/referentiel-action-origine-with-score.dto'; import { ReferentielActionType } from '../models/referentiel-action.dto'; -import { ReferentielType } from '../models/referentiel.enum'; +import { ReferentielId } from '../models/referentiel.enum'; import { ScoreJalon } from '../models/score-jalon.enum'; import LabellisationService from './labellisation.service'; import ReferentielsScoringSnapshotsService from './referentiels-scoring-snapshots.service'; @@ -102,7 +102,7 @@ export default class ReferentielsScoringService { async getOrCreateCurrentScore( collectiviteId: number, - referentielId: ReferentielType + referentielId: ReferentielId ) { let currentScore = await this.referentielsScoringSnapshotsService.get( collectiviteId, @@ -126,7 +126,7 @@ export default class ReferentielsScoringService { async checkCollectiviteAndReferentielWithAccess( collectiviteId: number, - referentielId: ReferentielType, + referentielId: ReferentielId, tokenInfo?: AuthenticatedUser, niveauAccesMinimum = NiveauAcces.LECTURE ): Promise { @@ -818,7 +818,7 @@ export default class ReferentielsScoringService { } async getReferentielActionStatuts( - referentielId: ReferentielType, + referentielId: ReferentielId, collectiviteId: number, date?: string, tokenInfo?: AuthenticatedUser, @@ -878,7 +878,7 @@ export default class ReferentielsScoringService { // Called explications to differentiate from discussion commentaire async getReferentielActionStatutExplications( - referentielId: ReferentielType, + referentielId: ReferentielId, collectiviteId: number, date?: string, tokenInfo?: AuthenticatedUser, @@ -987,7 +987,7 @@ export default class ReferentielsScoringService { } async computeScoreForMultipleCollectivite( - referentielId: ReferentielType, + referentielId: ReferentielId, parameters: GetReferentielMultipleScoresRequestType, tokenInfo?: AuthenticatedUser ): Promise { @@ -1037,7 +1037,7 @@ export default class ReferentielsScoringService { } async computeScoreForCollectivite( - referentielId: ReferentielType, + referentielId: ReferentielId, collectiviteId: number, parameters: GetReferentielScoresRequestType, tokenInfo?: AuthenticatedUser, @@ -1167,7 +1167,7 @@ export default class ReferentielsScoringService { collectiviteId, { date: parameters.date, - referentiel: referentielId as ReferentielType, + referentiel: referentielId as ReferentielId, }, undefined, // already checked collectiviteInfo @@ -1644,7 +1644,7 @@ export default class ReferentielsScoringService { referentielsOrigine.forEach((referentielOrigine) => { referentielsOriginePromiseScores.push( this.getClientScoresForCollectivite( - referentielOrigine as ReferentielType, + referentielOrigine as ReferentielId, collectiviteId, etoilesDefinitions ) @@ -1655,7 +1655,7 @@ export default class ReferentielsScoringService { referentielsOrigine.forEach((referentielOrigine) => { referentielsOriginePromiseScores.push( this.getPreAuditScoresForCollectivite( - referentielOrigine as ReferentielType, + referentielOrigine as ReferentielId, collectiviteId, undefined, etoilesDefinitions @@ -1667,7 +1667,7 @@ export default class ReferentielsScoringService { referentielsOrigine.forEach((referentielOrigine) => { referentielsOriginePromiseScores.push( this.getPostAuditScoresForCollectivite( - referentielOrigine as ReferentielType, + referentielOrigine as ReferentielId, collectiviteId, undefined, etoilesDefinitions @@ -1689,7 +1689,7 @@ export default class ReferentielsScoringService { referentielsOrigine.forEach((referentielOrigine) => { referentielsOriginePromiseScores.push( this.computeScoreForCollectivite( - referentielOrigine as ReferentielType, + referentielOrigine as ReferentielId, collectiviteId, { ...parameters, @@ -1836,20 +1836,20 @@ export default class ReferentielsScoringService { | undefined = undefined; if (jalon === ScoreJalon.SCORE_COURANT) { scoresResult = await this.getClientScoresForCollectivite( - referentiel.actionId as ReferentielType, + referentiel.actionId as ReferentielId, collectiviteId, etoiles ); } else if (jalon === ScoreJalon.PRE_AUDIT) { scoresResult = await this.getPreAuditScoresForCollectivite( - referentiel.actionId as ReferentielType, + referentiel.actionId as ReferentielId, collectiviteId, auditId!, etoiles ); } else if (jalon === ScoreJalon.POST_AUDIT) { scoresResult = await this.getPostAuditScoresForCollectivite( - referentiel.actionId as ReferentielType, + referentiel.actionId as ReferentielId, collectiviteId, auditId!, etoiles @@ -1876,7 +1876,7 @@ export default class ReferentielsScoringService { } async getClientScoresForCollectivite( - referentielId: ReferentielType, + referentielId: ReferentielId, collectiviteId: number, etoilesDefinition?: LabellisationEtoileMetaType[] ): Promise<{ @@ -1942,7 +1942,7 @@ export default class ReferentielsScoringService { } async getPreAuditScoresForCollectivite( - referentielId: ReferentielType, + referentielId: ReferentielId, collectiviteId: number, auditId?: number, etoilesDefinition?: LabellisationEtoileMetaType[] @@ -1971,7 +1971,7 @@ export default class ReferentielsScoringService { } async getPostAuditScoresForCollectivite( - referentielId: ReferentielType, + referentielId: ReferentielId, collectiviteId: number, auditId?: number, etoilesDefinition?: LabellisationEtoileMetaType[] @@ -2074,7 +2074,7 @@ export default class ReferentielsScoringService { } async checkScoreForCollectivite( - referentielId: ReferentielType, + referentielId: ReferentielId, collectiviteId: number, parameters: CheckReferentielScoresRequestType, hostUrl?: string, diff --git a/backend/src/referentiels/services/referentiels.service.spec.ts b/backend/src/referentiels/services/referentiels.service.spec.ts index 9b13db9e58..f2c5b6a2fe 100644 --- a/backend/src/referentiels/services/referentiels.service.spec.ts +++ b/backend/src/referentiels/services/referentiels.service.spec.ts @@ -3,12 +3,12 @@ import { Test } from '@nestjs/testing'; import ExpressionParserService from '../../personnalisations/services/expression-parser.service'; import ConfigurationService from '../../utils/config/configuration.service'; import SheetService from '../../utils/google-sheets/sheet.service'; +import { referentielIdEnumSchema } from '../index-domain'; import { ActionDefinitionAvecParentType } from '../models/action-definition.table'; import { CreateActionOrigineType } from '../models/action-origine.table'; import { ActionType } from '../models/action-type.enum'; import { ReferentielActionType } from '../models/referentiel-action.dto'; import { ReferentielDefinitionType } from '../models/referentiel-definition.table'; -import { ReferentielType } from '../models/referentiel.enum'; import ReferentielsService from './referentiels.service'; describe('ReferentielsService', () => { @@ -302,7 +302,7 @@ describe('ReferentielsService', () => { ]; expect( referentielsService.parseActionsOrigine( - ReferentielType.TE, + referentielIdEnumSchema.enum.te, 'te_3.5.4', `Eci_3.5.3.6 Eci_3.5.4.2`, @@ -338,7 +338,7 @@ Eci_3.5.4.2`, expect( referentielsService.parseActionsOrigine( - ReferentielType.TE, + referentielIdEnumSchema.enum.te, 'te_3.5.4', `Cae_5.1.4.4.1 (1) Cae_5.1.4.4.2 (0,5) @@ -351,7 +351,7 @@ Eci_1.3.2.4 (1)`, it('Invalid action id', async () => { expect(() => referentielsService.parseActionsOrigine( - ReferentielType.TE, + referentielIdEnumSchema.enum.te, 'te_3.5.4', `Cae 5.1.4.4.1`, refentielDefinitions @@ -360,7 +360,7 @@ Eci_1.3.2.4 (1)`, expect(() => referentielsService.parseActionsOrigine( - ReferentielType.TE, + referentielIdEnumSchema.enum.te, 'te_3.5.4', `test_.1.4.4.1`, refentielDefinitions @@ -369,7 +369,7 @@ Eci_1.3.2.4 (1)`, expect(() => referentielsService.parseActionsOrigine( - ReferentielType.TE, + referentielIdEnumSchema.enum.te, 'te_3.5.4', `test_1.1.4.4.1 0.5`, refentielDefinitions @@ -380,7 +380,7 @@ Eci_1.3.2.4 (1)`, it('Invalid action id referentiel', async () => { expect(() => referentielsService.parseActionsOrigine( - ReferentielType.TE, + referentielIdEnumSchema.enum.te, 'te_3.5.4', `Ca_5.1.4.4.1`, refentielDefinitions @@ -393,7 +393,7 @@ Eci_1.3.2.4 (1)`, it('Invalid ponderation', async () => { expect(() => referentielsService.parseActionsOrigine( - ReferentielType.TE, + referentielIdEnumSchema.enum.te, 'te_3.5.4', `Cae_5.1.4.4.1 (zero)`, refentielDefinitions diff --git a/backend/src/referentiels/services/referentiels.service.ts b/backend/src/referentiels/services/referentiels.service.ts index 70dec62743..cfda2699a4 100644 --- a/backend/src/referentiels/services/referentiels.service.ts +++ b/backend/src/referentiels/services/referentiels.service.ts @@ -59,7 +59,11 @@ import { CreateReferentielTagType, referentielTagTable, } from '../models/referentiel-tag.table'; -import { ReferentielType } from '../models/referentiel.enum'; +import { + ReferentielId, + referentielIdEnumSchema, + referentielIdEnumValues, +} from '../models/referentiel.enum'; @Injectable() export default class ReferentielsService { @@ -249,7 +253,7 @@ export default class ReferentielsService { } async getActionsOrigine( - referentielId: ReferentielType + referentielId: ReferentielId ): Promise { return await this.databaseService.db .select({ @@ -262,7 +266,7 @@ export default class ReferentielsService { eq(actionOrigineTable.origineActionId, actionDefinitionTable.actionId) ) .where( - eq(actionOrigineTable.referentielId, referentielId as ReferentielType) + eq(actionOrigineTable.referentielId, referentielId as ReferentielId) ) .orderBy(asc(actionOrigineTable.actionId)); } @@ -283,7 +287,7 @@ export default class ReferentielsService { } async getReferentiel( - referentielId: ReferentielType, + referentielId: ReferentielId, onlyForScoring?: boolean, getActionsOrigine?: boolean ): Promise { @@ -364,7 +368,7 @@ export default class ReferentielsService { } async getReferentielDefinition( - referentielId: ReferentielType + referentielId: ReferentielId ): Promise { this.logger.log(`Getting referentiel definition for ${referentielId}`); @@ -383,10 +387,10 @@ export default class ReferentielsService { return referentielDefinitions[0]; } - getReferentielSpreadsheetId(referentielId: ReferentielType): string { + getReferentielSpreadsheetId(referentielId: ReferentielId): string { if ( - referentielId === ReferentielType.TE || - referentielId === ReferentielType.TE_TEST + referentielId === referentielIdEnumSchema.enum.te || + referentielId === referentielIdEnumSchema.enum['te-test'] ) { return this.backendConfigurationService.get('REFERENTIEL_TE_SHEET_ID'); } @@ -396,16 +400,14 @@ export default class ReferentielsService { ); } - getReferentielIdFromActionId(actionId: string): ReferentielType { + getReferentielIdFromActionId(actionId: string): ReferentielId { const referentielId = actionId.split('_')[0]; - if ( - !Object.values(ReferentielType).includes(referentielId as ReferentielType) - ) { + if (!referentielIdEnumValues.includes(referentielId as ReferentielId)) { throw new UnprocessableEntityException( `Invalid referentiel id ${referentielId} for action ${actionId}` ); } - return referentielId as ReferentielType; + return referentielId as ReferentielId; } getLevelFromActionId(actionId: string): number { @@ -448,7 +450,7 @@ export default class ReferentielsService { } parseActionsOrigine( - referentielId: ReferentielType, + referentielId: ReferentielId, actionId: string, origine: string, referentielDefinitions: ReferentielDefinitionType[], @@ -525,12 +527,12 @@ export default class ReferentielsService { async createReferentielTagsIfNeeded(): Promise { const referentielTags: CreateReferentielTagType[] = [ { - ref: ReferentielType.CAE, + ref: referentielIdEnumSchema.enum.cae, nom: 'CAE', type: 'Catalogue', }, { - ref: ReferentielType.ECI, + ref: referentielIdEnumSchema.enum.eci, nom: 'ECI', type: 'Catalogue', }, @@ -547,7 +549,7 @@ export default class ReferentielsService { } async importReferentiel( - referentielId: ReferentielType + referentielId: ReferentielId ): Promise { const spreadsheetId = this.getReferentielSpreadsheetId(referentielId); diff --git a/backend/src/referentiels/snapshots/score-snaphots.router.ts b/backend/src/referentiels/snapshots/score-snaphots.router.ts index 69340bfbe4..079a2eb0dd 100644 --- a/backend/src/referentiels/snapshots/score-snaphots.router.ts +++ b/backend/src/referentiels/snapshots/score-snaphots.router.ts @@ -1,13 +1,13 @@ +import { TrpcService } from '@/backend/utils/trpc/trpc.service'; import { Injectable } from '@nestjs/common'; import z from 'zod'; -import { TrpcService } from '@/backend/utils/trpc/trpc.service'; -import { ReferentielType } from '../models/referentiel.enum'; +import { referentielIdEnumSchema } from '../models/referentiel.enum'; import { ScoreJalon } from '../models/score-jalon.enum'; import ReferentielsScoringSnapshotsService from '../services/referentiels-scoring-snapshots.service'; import ReferentielsScoringService from '../services/referentiels-scoring.service'; export const getScoreSnapshotInfosTrpcRequestSchema = z.object({ - referentielId: z.nativeEnum(ReferentielType), + referentielId: referentielIdEnumSchema, collectiviteId: z.number().int(), parameters: z.object({ typesJalon: z.nativeEnum(ScoreJalon).array(), @@ -15,7 +15,7 @@ export const getScoreSnapshotInfosTrpcRequestSchema = z.object({ }); export const getFullScoreSnapshotTrpcRequestSchema = z.object({ - referentielId: z.nativeEnum(ReferentielType), + referentielId: referentielIdEnumSchema, collectiviteId: z.number().int(), snapshotRef: z.string(), }); @@ -41,7 +41,7 @@ export class ScoreSnapshotsRouter { getCurrentFullScore: this.trpc.authedProcedure .input( z.object({ - referentielId: z.nativeEnum(ReferentielType), + referentielId: referentielIdEnumSchema, collectiviteId: z.number().int(), }) ) diff --git a/backend/src/referentiels/snapshots/score-snapshots.router.e2e-spec.ts b/backend/src/referentiels/snapshots/score-snapshots.router.e2e-spec.ts index a66a6f7952..e922f49756 100644 --- a/backend/src/referentiels/snapshots/score-snapshots.router.e2e-spec.ts +++ b/backend/src/referentiels/snapshots/score-snapshots.router.e2e-spec.ts @@ -5,8 +5,8 @@ import { getAuthUser } from '../../../test/auth-utils'; import { getCollectiviteIdBySiren } from '../../../test/collectivites-utils'; import { AuthenticatedUser } from '../../auth/models/auth.models'; import { AppRouter, TrpcRouter } from '../../utils/trpc/trpc.router'; +import { referentielIdEnumSchema } from '../index-domain'; import { ScoreSnapshotInfoType } from '../models/get-score-snapshots.response'; -import { ReferentielType } from '../models/referentiel.enum'; import { ScoreJalon } from '../models/score-jalon.enum'; type ComputeScoreInput = inferProcedureInput< @@ -28,7 +28,7 @@ describe('ScoreSnapshotsRouter', () => { const caller = router.createCaller({ user: null }); const input: ComputeScoreInput = { - referentielId: ReferentielType.CAE, + referentielId: referentielIdEnumSchema.enum.cae, collectiviteId: 1, parameters: { snapshot: true, @@ -46,7 +46,7 @@ describe('ScoreSnapshotsRouter', () => { const caller = router.createCaller({ user: yoloDodoUser }); const input: ComputeScoreInput = { - referentielId: ReferentielType.CAE, + referentielId: referentielIdEnumSchema.enum.cae, collectiviteId: rhoneAggloCollectiviteId, parameters: { snapshot: true, @@ -65,7 +65,7 @@ describe('ScoreSnapshotsRouter', () => { const caller = router.createCaller({ user: yoloDodoUser }); const input: ComputeScoreInput = { - referentielId: ReferentielType.CAE, + referentielId: referentielIdEnumSchema.enum.cae, collectiviteId: 1, parameters: { snapshot: true, @@ -83,7 +83,7 @@ describe('ScoreSnapshotsRouter', () => { const responseSnapshotList = await caller.referentiels.snapshots.listSummary({ collectiviteId: 1, - referentielId: ReferentielType.CAE, + referentielId: referentielIdEnumSchema.enum.cae, parameters: { typesJalon: [ScoreJalon.DATE_PERSONNALISEE], }, @@ -122,7 +122,7 @@ describe('ScoreSnapshotsRouter', () => { // delete the snapshot await caller.referentiels.snapshots.delete({ collectiviteId: 1, - referentielId: ReferentielType.CAE, + referentielId: referentielIdEnumSchema.enum.cae, snapshotRef: 'user-test-trpc', }); @@ -130,7 +130,7 @@ describe('ScoreSnapshotsRouter', () => { const responseSnapshotListAfterDelete = await caller.referentiels.snapshots.listSummary({ collectiviteId: 1, - referentielId: ReferentielType.CAE, + referentielId: referentielIdEnumSchema.enum.cae, parameters: { typesJalon: [ScoreJalon.DATE_PERSONNALISEE], }, diff --git a/backend/src/referentiels/update-action-statut/update-action-statut.router.e2e-spec.ts b/backend/src/referentiels/update-action-statut/update-action-statut.router.e2e-spec.ts index e783e091d5..d4a9cb31c1 100644 --- a/backend/src/referentiels/update-action-statut/update-action-statut.router.e2e-spec.ts +++ b/backend/src/referentiels/update-action-statut/update-action-statut.router.e2e-spec.ts @@ -4,7 +4,7 @@ import { getAuthUser } from '../../../test/auth-utils'; import { getCollectiviteIdBySiren } from '../../../test/collectivites-utils'; import { AppRouter, TrpcRouter } from '../../utils/trpc/trpc.router'; import { ActionScoreType } from '../models/action-score.dto'; -import { ReferentielType } from '../models/referentiel.enum'; +import { referentielIdEnumSchema } from '../models/referentiel.enum'; import { AuthenticatedUser } from './../../auth/models/auth.models'; type Input = inferProcedureInput< @@ -127,7 +127,7 @@ describe('UpdateActionStatutRouter', () => { // Check that the current score has been correctly updated & saved const currentFullCurentScore = await caller.referentiels.snapshots.getCurrentFullScore({ - referentielId: ReferentielType.CAE, + referentielId: referentielIdEnumSchema.enum.cae, collectiviteId: 1, }); expect(currentFullCurentScore.scores.score).toEqual( diff --git a/packages/api/src/indicateurs/actions/indicateur.fetch.ts b/packages/api/src/indicateurs/actions/indicateur.fetch.ts index 4778d51c88..48e74656b3 100644 --- a/packages/api/src/indicateurs/actions/indicateur.fetch.ts +++ b/packages/api/src/indicateurs/actions/indicateur.fetch.ts @@ -1,3 +1,4 @@ +import { Source, SourceMetadonnee } from '@/domain/indicateurs'; import { Thematique } from '@/domain/shared'; import { objectToCamel } from 'ts-case-convert'; import { @@ -9,7 +10,6 @@ import { Personne } from '../../collectivites/shared/domain/personne.schema'; import { Tables } from '../../database.types'; import { FicheResume } from '../../plan-actions/domain/fiche-action.schema'; import { DBClient } from '../../typeUtils'; -import { Source, SourceMetadonnee } from '../domain'; import { IndicateurChartInfo, IndicateurDefinition, diff --git a/packages/api/src/indicateurs/actions/indicateur.save.test.ts b/packages/api/src/indicateurs/actions/indicateur.save.test.ts index 264b9d4872..525ca54032 100644 --- a/packages/api/src/indicateurs/actions/indicateur.save.test.ts +++ b/packages/api/src/indicateurs/actions/indicateur.save.test.ts @@ -6,8 +6,6 @@ import { FicheResume } from '../../plan-actions/domain/fiche-action.schema'; import { signIn, signOut } from '../../tests/auth'; import { dbAdmin, supabase } from '../../tests/supabase'; import { testReset } from '../../tests/testReset'; -import { IndicateurDefinitionInsert } from '../domain/definition.schema'; -import { Valeur } from '../domain/valeur.schema'; import { selectIndicateurCategoriesUtilisateur, selectIndicateurDefinition, @@ -94,7 +92,7 @@ describe('Test indicateur.save', async () => { }); test('Test insertIndicateurDefinition', async () => { - const def: IndicateurDefinitionInsert = { + const def: Parameters['1'] = { titre: 'test', collectiviteId: 1, thematiques: [{ id: 1, nom: '' }], @@ -111,7 +109,7 @@ describe('Test indicateur.save', async () => { }); test('Test upsertIndicateurValeur', async () => { - const valeur: Valeur = { + const valeur: Parameters['1'] = { collectiviteId: 1, indicateurId: 1, resultat: 1.3, diff --git a/packages/api/src/indicateurs/actions/indicateur.save.ts b/packages/api/src/indicateurs/actions/indicateur.save.ts index c14bbeefd7..253febd2b9 100644 --- a/packages/api/src/indicateurs/actions/indicateur.save.ts +++ b/packages/api/src/indicateurs/actions/indicateur.save.ts @@ -1,17 +1,15 @@ import { Tag, TagInsert } from '@/domain/collectivites'; -import { Thematique } from '@/domain/shared'; +import { indicateurDefinitionSchemaInsert } from '@/domain/indicateurs'; +import { Thematique, thematiqueSchema } from '@/domain/shared'; import { isNil } from 'es-toolkit/predicate'; import { objectToSnake } from 'ts-case-convert'; +import { z } from 'zod'; import { Personne } from '../../collectivites/shared/domain/personne.schema'; import { selectTags } from '../../shared/actions/tag.fetch'; import { insertTags } from '../../shared/actions/tag.save'; import { DBClient, TablesInsert } from '../../typeUtils'; -import { - IndicateurDefinition, - IndicateurDefinitionInsert, - indicateurDefinitionSchemaInsert, -} from '../domain/definition.schema'; -import { Valeur, valeurSchema } from '../domain/valeur.schema'; +import { Valeur, valeurSchema } from '../domain'; +import { IndicateurDefinition } from '../domain/definition.schema'; import { IndicateurImportSource, getValeursComparaison, @@ -86,6 +84,21 @@ export async function updateIndicateurFavoriCollectivite( }); } +const schema = indicateurDefinitionSchemaInsert + .pick({ + titre: true, + collectiviteId: true, + unite: true, + description: true, + }) + .partial({ unite: true }) + .extend({ + thematiques: thematiqueSchema + .pick({ id: true, nom: true }) + .array() + .optional(), + }); + /** * Ajoute un indicateur personnalisé * @param dbClient client supabase @@ -94,9 +107,10 @@ export async function updateIndicateurFavoriCollectivite( */ export async function insertIndicateurDefinition( dbClient: DBClient, - indicateur: IndicateurDefinitionInsert + indicateur: z.infer ): Promise { - indicateurDefinitionSchemaInsert.parse(indicateur); // Vérifie le type + schema.parse(indicateur); // Vérifie le type + const { data, error } = await dbClient .from('indicateur_definition') .insert({ diff --git a/packages/api/src/indicateurs/actions/source.fetch.test.ts b/packages/api/src/indicateurs/actions/source.fetch.test.ts deleted file mode 100644 index 17f035d3b1..0000000000 --- a/packages/api/src/indicateurs/actions/source.fetch.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { beforeAll, expect, test } from 'vitest'; -import { signIn, signOut } from '../../tests/auth'; -import { supabase } from '../../tests/supabase'; -import { testReset } from '../../tests/testReset'; -import { selectSources } from './source.fetch'; - -beforeAll(async () => { - await signIn('yolododo'); - await testReset(); - - return async () => { - await signOut(); - }; -}); - -test('Test selectSources', async () => { - const data = await selectSources(supabase); - expect(data).not.toBeNull(); - expect(data.length).toBeGreaterThan(1); -}); diff --git a/packages/api/src/indicateurs/actions/source.fetch.ts b/packages/api/src/indicateurs/actions/source.fetch.ts deleted file mode 100644 index 4bf67c478f..0000000000 --- a/packages/api/src/indicateurs/actions/source.fetch.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {DBClient} from "../../typeUtils"; -import {Source} from "../domain/source.schema"; - -/** - * Recupère les sources - * @param dbClient client supabase - * @return liste des sources existantes - */ -export async function selectSources(dbClient : DBClient): Promise{ - const {data, error} = await dbClient - .from('indicateur_source') - .select(); - - return data ? data as Source[] : []; -} \ No newline at end of file diff --git a/packages/api/src/indicateurs/domain/index.ts b/packages/api/src/indicateurs/domain/index.ts index 6677590e10..577aea95aa 100644 --- a/packages/api/src/indicateurs/domain/index.ts +++ b/packages/api/src/indicateurs/domain/index.ts @@ -1,5 +1,4 @@ export * from './categorie.schema'; export * from './definition.schema'; -export * from './source.schema'; -export * from './valeur.schema'; export * from './fetch-options.schema'; +export * from './valeur.schema'; diff --git a/packages/api/src/indicateurs/domain/source.schema.ts b/packages/api/src/indicateurs/domain/source.schema.ts deleted file mode 100644 index f9b0c0ba30..0000000000 --- a/packages/api/src/indicateurs/domain/source.schema.ts +++ /dev/null @@ -1,34 +0,0 @@ -import {z} from 'zod'; -import {valeurSchema} from "./valeur.schema"; - -/** - * Schéma zod des métadonnées d'une source pour une valeur d'indicateur - */ -export const sourceMetadonneeSchema = z.object({ - id : z.number(), - source : z.string(), - dateVersion : z.string().datetime(), - nomDonnee : z.string().nullable(), - diffuseur : z.string().nullable(), - producteur : z.string().nullable(), - methodologie : z.string().nullable(), - limites : z.string().nullable() -}); -/** - * Type TS des métadonnées d'une source pour une valeur d'indicateur - */ -export type SourceMetadonnee = z.input; - -/** - * Schéma zod d'une source de donnée - */ -export const sourceSchema = z.object ({ - id : z.string(), - libelle : z.string(), - ordreAffichage : z.number().optional().nullable() -}); -/** - * Type TS d'une source de donnée - */ -export type Source = z.input; - diff --git a/packages/api/src/indicateurs/domain/valeur.schema.ts b/packages/api/src/indicateurs/domain/valeur.schema.ts index 15315e04bc..2f458f91b7 100644 --- a/packages/api/src/indicateurs/domain/valeur.schema.ts +++ b/packages/api/src/indicateurs/domain/valeur.schema.ts @@ -1,56 +1,82 @@ -import {z} from 'zod'; -import {sourceMetadonneeSchema} from "./source.schema"; +import { + indicateurValeurSchemaInsert, + sourceMetadonneeSchema, +} from '@/domain/indicateurs'; +import { z } from 'zod'; /** * Schéma zod d'une valeur d'indicateur */ -export const valeurSchema = z.object({ - id : z.number().optional().nullable(), - collectiviteId : z.number(), - indicateurId : z.number(), - source : sourceMetadonneeSchema.optional().nullable(), - resultat : z.number().optional().nullable(), - objectif : z.number().optional().nullable(), - estimation : z.number().optional().nullable(), - resultatCommentaire : z.string().optional().nullable(), - objectifCommentaire : z.string().optional().nullable(), - annee : z.number() -}); +export const valeurSchema = indicateurValeurSchemaInsert + .omit({ + dateValeur: true, + }) + .extend({ + annee: z.number(), + source: sourceMetadonneeSchema + // .pick({ + // id: true, + // dateVersion: true, + // diffuseur:true + // }) + .optional() + .nullable(), + }); + +// export const valeurSchema = +// z.object({ +// id: z.number().optional().nullable(), +// collectiviteId: z.number(), +// indicateurId: z.number(), +// source: sourceMetadonneeSchema +// .pick({ +// id: true, +// }) +// .optional() +// .nullable(), +// resultat: z.number().optional().nullable(), +// objectif: z.number().optional().nullable(), +// estimation: z.number().optional().nullable(), +// resultatCommentaire: z.string().optional().nullable(), +// objectifCommentaire: z.string().optional().nullable(), +// annee: z.number(), +// }); /** * Type TS d'une valeur d'indicateur */ export type Valeur = z.input; - /** * Schéma zod d'une ligne de comparaison entre les valeurs utilisateurs et source */ export const valeurComparaisonLigneSchema = z.object({ - conflit: z.boolean(), - annee : z.number(), - idAEcraser : z.number().nullable(), - idAAppliquer : z.number(), - valeurAEcraser: z.number().nullable(), - valeurAAppliquer: z.number(), - source : z.string() + conflit: z.boolean(), + annee: z.number(), + idAEcraser: z.number().nullable(), + idAAppliquer: z.number(), + valeurAEcraser: z.number().nullable(), + valeurAAppliquer: z.number(), + source: z.string(), }); /** * Type TS d'une ligne de comparaison entre les valeurs utilisateurs et source */ -export type ValeurComparaisonLigne = z.input; +export type ValeurComparaisonLigne = z.input< + typeof valeurComparaisonLigneSchema +>; /** * Schéma zod pour la comparaison des valeurs utilisateurs avec les valeurs d'une source */ export const valeurComparaisonSchema = z.object({ - lignes : valeurComparaisonLigneSchema.array(), - conflits : z.number(), - ajouts : z.number() + lignes: valeurComparaisonLigneSchema.array(), + conflits: z.number(), + ajouts: z.number(), }); /** * Type TS pour la comparaison des valeurs utilisateurs avec les valeurs d'une source */ -export type ValeurComparaison = z.input; \ No newline at end of file +export type ValeurComparaison = z.input; diff --git a/packages/api/src/referentiel/domain/action.schema.ts b/packages/api/src/referentiel/domain/action.schema.ts index b0f5725d05..36dc3fb138 100644 --- a/packages/api/src/referentiel/domain/action.schema.ts +++ b/packages/api/src/referentiel/domain/action.schema.ts @@ -1,4 +1,4 @@ -import { referentielTypeEnumSchema } from '@/domain/referentiels'; +import { referentielIdEnumSchema } from '@/domain/referentiels'; import { z } from 'zod'; /** @@ -7,5 +7,5 @@ import { z } from 'zod'; export const actionSchema = z.object({ id: z.string(), parent: z.string().nullish(), - referentiel: referentielTypeEnumSchema, + referentiel: referentielIdEnumSchema, });