From 718d234a5de51089dbdb8d06cf887d1b8dbcd947 Mon Sep 17 00:00:00 2001 From: Amandine Date: Thu, 12 Sep 2024 18:22:45 +0200 Subject: [PATCH 01/22] =?UTF-8?q?Backend=20-=20Ajoute=20la=20connexion=20?= =?UTF-8?q?=C3=A0=20l'API=20directus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/config/configuration.model.ts | 4 + .../src/directus/models/directus.models.ts | 111 ++++++++++++++++++ .../src/directus/service/directus.service.ts | 71 +++++++++++ 3 files changed, 186 insertions(+) create mode 100644 backend/src/directus/models/directus.models.ts create mode 100644 backend/src/directus/service/directus.service.ts diff --git a/backend/src/config/configuration.model.ts b/backend/src/config/configuration.model.ts index 06bc981607..7604d99116 100644 --- a/backend/src/config/configuration.model.ts +++ b/backend/src/config/configuration.model.ts @@ -35,6 +35,10 @@ export const backendConfigurationSchema = z.object({ description: 'Identifiant du dossier Google Drive pour le stockage des résultats de calcul de la trajectoire SNBC', }), + DIRECTUS_API_KEY: z.string().min(1).openapi({ + description: + "Clé pour la connexion à l'api de Directus" + }), }); export type BackendConfigurationType = z.infer< typeof backendConfigurationSchema diff --git a/backend/src/directus/models/directus.models.ts b/backend/src/directus/models/directus.models.ts new file mode 100644 index 0000000000..03769d947f --- /dev/null +++ b/backend/src/directus/models/directus.models.ts @@ -0,0 +1,111 @@ +/** + * Liste les types retournés par l'api de directus + */ + + +export type Link = { + label: string; + url: string; +}; + +export type Niveau = { + niveau: number; + nom: string; + notice?: string | null; +}; + +export type Partenaire = { + id: number; + nom: string; +}; + +export type ImpactCarbone = { + id: number; + nom: string; +}; + +export type Typologie = { + id: number; + nom: string; +}; + +export type SousThematiques = { + id: number; + action_impact_id: number; + sous_thematique_id?: number; // Ne devrait pas être optionnel +}; + +export type EffetsAttendus = { + id: number; + action_impact_id: number; + action_impact_effet_attendu_id: number; +}; + +export type Thematiques = { + id: number; + action_impact_id: number; + thematique_id: number; +}; + +export type Partenaires = { + id: number; + action_impact_id: number; + action_impact_partenaire_id: number; +}; + +export type IndicateursSuivi = { + id: number; + action_impact_id: number; + indicateur_suivi_id: number; +}; + +export type Indicateurs = { + id: number; + action_impact_id: number; + indicateur_predefini_id?: string; +}; + +export type ActionsReferentiel = { + id: number; + action_impact_id: number; + action_referentiel_id: string; +}; + +export type ActionImpact = { + id: number; + titre: string; + description_courte: string; + fourchette_budgetaire: Niveau; + description_longue?: string; + temps_de_mise_en_oeuvre: Niveau; + ressources_externes?: Link[]; + rex?: Link[]; + subventions_mobilisables?: Link[]; + typologie: Typologie; + notes_travail?: string; + statut: string; + elements_budgetaires?: string; + indicateur_impact_carbone?: ImpactCarbone; + competences_communales?: boolean; + independamment_competences?: boolean; + sous_thematiques: SousThematiques[]; + effets_attendus: EffetsAttendus[]; + thematiques: Thematiques[]; + partenaires: Partenaires[]; + indicateurs_suivi: IndicateursSuivi[]; + indicateurs: Indicateurs[]; + actions_referentiel: ActionsReferentiel[]; + banatic_competences_parentes: any[]; + banatic_competences: any[]; +}; + +export type Thematique = { + id: number; + nom: string; +}; + +export type SousThematique = { + id: number; + nom: string; + thematique?: Thematique | null; //une thématique au moins est cassée +}; diff --git a/backend/src/directus/service/directus.service.ts b/backend/src/directus/service/directus.service.ts new file mode 100644 index 0000000000..26f16b8cc3 --- /dev/null +++ b/backend/src/directus/service/directus.service.ts @@ -0,0 +1,71 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { + ActionImpact, + Partenaire, + SousThematique, +} from '../models/directus.models'; +import ConfigurationService from 'backend/src/config/configuration.service'; + +@Injectable() +export default class DirectusService { + private readonly logger = new Logger(DirectusService.name); + + constructor( + private readonly configurationService: ConfigurationService, + ) {} + + private readonly directusKey = + this.configurationService.get('DIRECTUS_API_KEY'); + private readonly headers = { Authorization: `Bearer ${this.directusKey}` }; + private readonly directusUrl = 'https://tet.directus.app'; + + /** + * Renvoie une liste d'élements d'une collection Directus donnée + * On trouve les noms des collections dans l'url de Directus ex : + * action_referentiel: https://tet.directus.app/admin/content/action_referentiel + * @param collection nom de la table à récupérer de directus + * @return le résultat de la requête + */ + async getFromDirectus(collection: string): Promise { + const response = await fetch( + `${this.directusUrl}/items/${collection}?fields[]=*.*&limit=-1`, + { + method: 'GET', + headers: this.headers, + }, + ); + + if (!response.ok) { + return null; + } + this.logger.log(`Récupération de la table ${collection} dans directus`); + return await response.json(); + } + + /** + * Récupère les actions à impact provenant de directus + * @return les actions à impact + */ + async getActionsImpactFromDirectus(): Promise { + return (await this.getFromDirectus('action_impact')) + ?.data as ActionImpact[]; + } + + /** + * Récupère les sous thématiques provenant de directus + * @return les sous thématiques + */ + async getSousThematiquesFromDirectus(): Promise { + return (await this.getFromDirectus('sous_thematique')) + ?.data as SousThematique[]; + } + + /** + * Récupère les partenaires provenant de directus + * @return les partenaires + */ + async getPartenairesFromDirectus(): Promise { + return (await this.getFromDirectus('action_impact_partenaire')) + ?.data as Partenaire[]; + } +} From bf729dc5d12e21dc3ae6be51b97538cd7cdd5db4 Mon Sep 17 00:00:00 2001 From: Amandine Date: Thu, 12 Sep 2024 18:23:23 +0200 Subject: [PATCH 02/22] =?UTF-8?q?Backend=20-=20Ajoute=20la=20connexion=20?= =?UTF-8?q?=C3=A0=20l'API=20brevo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/auth/models/user-crm.dto.ts | 8 ++ backend/src/brevo/models/brevo.models.ts | 7 ++ backend/src/brevo/service/brevo.service.ts | 125 +++++++++++++++++++++ backend/src/config/configuration.model.ts | 4 + 4 files changed, 144 insertions(+) create mode 100644 backend/src/auth/models/user-crm.dto.ts create mode 100644 backend/src/brevo/models/brevo.models.ts create mode 100644 backend/src/brevo/service/brevo.service.ts diff --git a/backend/src/auth/models/user-crm.dto.ts b/backend/src/auth/models/user-crm.dto.ts new file mode 100644 index 0000000000..9b014d19c2 --- /dev/null +++ b/backend/src/auth/models/user-crm.dto.ts @@ -0,0 +1,8 @@ +export type userCrm = { + prenom: string; + nom: string; + email: string; + telephone: string | null; + creation: string | null; + derniereConnexion: string | null; +}; diff --git a/backend/src/brevo/models/brevo.models.ts b/backend/src/brevo/models/brevo.models.ts new file mode 100644 index 0000000000..ab2411d827 --- /dev/null +++ b/backend/src/brevo/models/brevo.models.ts @@ -0,0 +1,7 @@ +export enum BrevoLists { + ID_LIST_BREVO_ONBOARDING_PAI = 87, + ID_LIST_BREVO_ONBOARDING_GENERAL = 18, + ID_LIST_BREVO_CREATION_PA = 75, + ID_LIST_BREVO_SONDAGE_PA_1 = 76, + ID_LIST_BREVO_SONDAGE_PA_2 = 77, +} diff --git a/backend/src/brevo/service/brevo.service.ts b/backend/src/brevo/service/brevo.service.ts new file mode 100644 index 0000000000..d6c8ac981d --- /dev/null +++ b/backend/src/brevo/service/brevo.service.ts @@ -0,0 +1,125 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { userCrm } from '../../auth/models/user-crm.dto'; +import ConfigurationService from '../../config/configuration.service'; + +@Injectable() +export default class BrevoService { + private readonly logger = new Logger(BrevoService.name); + + constructor( + private readonly configurationService: ConfigurationService, + ) {} + + private readonly brevoKey = + this.configurationService.get('BREVO_API_KEY'); + private readonly headers = { + Accept: 'application/json', + 'Api-key': `${this.brevoKey}`, + 'Content-type': 'application/json', + }; + private readonly urlContact = 'https://api.brevo.com/v3/contacts/'; + + /** + * Récupère les informations d'un contact Brevo via son email + * https://developers.brevo.com/reference/getcontactinfo-1 + * @param email + * @return le contact sous format json, null s'il n'existe pas + */ + async getContactByEmail(email: string): Promise { + const response = await fetch(this.urlContact + email, { + method: 'GET', + headers: this.headers, + }); + if (!response.ok) { + if (response.status == 404) { + // L'utilisateur n'existe pas dans Brevo + return null; + } else { + throw new Error(`Error! status: ${response.status}`); + } + } + return await response.json(); + } + + /** + * Ajoute des contacts à une liste Brevo via leurs emails + * https://developers.brevo.com/reference/addcontacttolist-1 + * @param emails + * @param list + */ + async addContactsToList(emails: string[], list: number): Promise { + const response = await fetch( + this.urlContact + 'lists/' + list + '/contacts/add', + { + method: 'POST', + headers: this.headers, + body: JSON.stringify({ emails: emails }), + }, + ); + if (!response.ok) { + console.log( + 'Les contacts ' + + emails + + " n'ont pas pu être ajouté à la liste #" + + list + + '.', + ); + return null; + } + return await response.json(); + } + + /** + * Ajoute un contact à Brevo + * https://developers.brevo.com/reference/createcontact + * @param user (nom, prenom, derniere_connexion, email) + */ + async addContact(user: userCrm): Promise { + const response = await fetch(this.urlContact, { + method: 'POST', + headers: this.headers, + body: JSON.stringify({ + attributes: { + NOM: user.nom, + PRENOM: user.prenom, + DATECONNEXION: user.derniereConnexion, + }, + updateEnabled: false, + email: user.email, + }), + }); + if (!response.ok) { + console.log('Le contact ' + user.email + " n'a pas pu être créé."); + return null; + } + return await response.json(); + } + + /** + * Enlève des contacts à une liste Brevo via leurs emails + * https://developers.brevo.com/reference/removecontactfromlist + * @param emails + * @param list + */ + async removeContactsFromList(emails: string[], list: number): Promise { + const response = await fetch( + this.urlContact + 'lists/' + list + '/contacts/remove', + { + method: 'POST', + headers: this.headers, + body: JSON.stringify({ emails: emails }), + }, + ); + if (!response.ok) { + console.log( + 'Les contacts ' + + emails + + " n'ont pas pu être enlevé de la liste #" + + list + + '.', + ); + return null; + } + return await response.json(); + } +} diff --git a/backend/src/config/configuration.model.ts b/backend/src/config/configuration.model.ts index 7604d99116..771d817c8f 100644 --- a/backend/src/config/configuration.model.ts +++ b/backend/src/config/configuration.model.ts @@ -39,6 +39,10 @@ export const backendConfigurationSchema = z.object({ description: "Clé pour la connexion à l'api de Directus" }), + BREVO_API_KEY: z.string().min(1).openapi({ + description: + "Clé pour la connexion à l'api de Brevo" + }), }); export type BackendConfigurationType = z.infer< typeof backendConfigurationSchema From ffa3dedc2376738226f5ba23bd1c3009fa9ed121 Mon Sep 17 00:00:00 2001 From: Amandine Date: Thu, 12 Sep 2024 18:24:10 +0200 Subject: [PATCH 03/22] Backend - Ajoute les tags --- .../taxonomie/models/categorie-tag.table.ts | 12 +++++ .../taxonomie/models/financeur-tag.table.ts | 10 +++++ .../taxonomie/models/partenaire-tag.table.ts | 4 +- .../taxonomie/models/personne-tag.table.ts | 4 +- .../src/taxonomie/models/service-tag.table.ts | 4 +- .../taxonomie/models/structure-tag.table.ts | 10 +++++ backend/src/taxonomie/models/tag.basetable.ts | 4 +- backend/src/taxonomie/services/tag.service.ts | 45 +++++++++++++++++++ 8 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 backend/src/taxonomie/models/categorie-tag.table.ts create mode 100644 backend/src/taxonomie/models/financeur-tag.table.ts create mode 100644 backend/src/taxonomie/models/structure-tag.table.ts create mode 100644 backend/src/taxonomie/services/tag.service.ts diff --git a/backend/src/taxonomie/models/categorie-tag.table.ts b/backend/src/taxonomie/models/categorie-tag.table.ts new file mode 100644 index 0000000000..c990cd2176 --- /dev/null +++ b/backend/src/taxonomie/models/categorie-tag.table.ts @@ -0,0 +1,12 @@ +import { boolean, integer, pgTable, timestamp, uuid } from 'drizzle-orm/pg-core'; +import { TagBase } from './tag.basetable'; + +export const categorieTagTable = pgTable('categorie_tag', { + ...TagBase, + groupementId: integer('groupement_id'), // TODO .references(() => groupementTable.id) + visible: boolean('visible').default(true), + createdAt: timestamp('created_at', { withTimezone: true }) + .notNull() + .defaultNow(), + createdBy: uuid('created_by'), // TODO references auth.uid +}); diff --git a/backend/src/taxonomie/models/financeur-tag.table.ts b/backend/src/taxonomie/models/financeur-tag.table.ts new file mode 100644 index 0000000000..ab2d8711e9 --- /dev/null +++ b/backend/src/taxonomie/models/financeur-tag.table.ts @@ -0,0 +1,10 @@ +import { pgTable, uniqueIndex } from 'drizzle-orm/pg-core'; +import { TagBase } from './tag.basetable'; + +export const financeurTagTable = pgTable('financeur_tag', TagBase, (table) => { + return { + financeurTagNomCollectiviteIdKey: uniqueIndex( + 'financeur_tag_nom_collectivite_id_key', + ).on(table.nom, table.collectiviteId), + }; +}); diff --git a/backend/src/taxonomie/models/partenaire-tag.table.ts b/backend/src/taxonomie/models/partenaire-tag.table.ts index 8a9e0524bc..00dcecc6de 100644 --- a/backend/src/taxonomie/models/partenaire-tag.table.ts +++ b/backend/src/taxonomie/models/partenaire-tag.table.ts @@ -6,9 +6,9 @@ export const partenaireTagTable = pgTable( TagBase, (table) => { return { - partenaire_tag_nom_collectivite_id_key: uniqueIndex( + partenaireTagNomCollectiviteIdKey: uniqueIndex( 'partenaire_tag_nom_collectivite_id_key', - ).on(table.nom, table.collectivite_id), + ).on(table.nom, table.collectiviteId), }; }, ); diff --git a/backend/src/taxonomie/models/personne-tag.table.ts b/backend/src/taxonomie/models/personne-tag.table.ts index 59b312753c..0ae6529f5e 100644 --- a/backend/src/taxonomie/models/personne-tag.table.ts +++ b/backend/src/taxonomie/models/personne-tag.table.ts @@ -3,8 +3,8 @@ import { TagBase } from './tag.basetable'; export const personneTagTable = pgTable('personne_tag', TagBase, (table) => { return { - personne_tag_nom_collectivite_id_key: uniqueIndex( + personneTagNomCollectiviteIdKey: uniqueIndex( 'personne_tag_nom_collectivite_id_key', - ).on(table.nom, table.collectivite_id), + ).on(table.nom, table.collectiviteId), }; }); diff --git a/backend/src/taxonomie/models/service-tag.table.ts b/backend/src/taxonomie/models/service-tag.table.ts index bbaf4c8904..dc0eafc7e7 100644 --- a/backend/src/taxonomie/models/service-tag.table.ts +++ b/backend/src/taxonomie/models/service-tag.table.ts @@ -3,8 +3,8 @@ import { TagBase } from './tag.basetable'; export const serviceTagTable = pgTable('service_tag', TagBase, (table) => { return { - service_tag_nom_collectivite_id_key: uniqueIndex( + serviceTagNomCollectiviteIdKey: uniqueIndex( 'service_tag_nom_collectivite_id_key', - ).on(table.nom, table.collectivite_id), + ).on(table.nom, table.collectiviteId), }; }); diff --git a/backend/src/taxonomie/models/structure-tag.table.ts b/backend/src/taxonomie/models/structure-tag.table.ts new file mode 100644 index 0000000000..04ec34b379 --- /dev/null +++ b/backend/src/taxonomie/models/structure-tag.table.ts @@ -0,0 +1,10 @@ +import { pgTable, uniqueIndex } from 'drizzle-orm/pg-core'; +import { TagBase } from './tag.basetable'; + +export const structureTagTable = pgTable('structure_tag', TagBase, (table) => { + return { + structureTagNomCollectiviteIdKey: uniqueIndex( + 'structure_tag_nom_collectivite_id_key', + ).on(table.nom, table.collectiviteId), + }; +}); diff --git a/backend/src/taxonomie/models/tag.basetable.ts b/backend/src/taxonomie/models/tag.basetable.ts index c007b2e3cc..1580936aac 100644 --- a/backend/src/taxonomie/models/tag.basetable.ts +++ b/backend/src/taxonomie/models/tag.basetable.ts @@ -1,10 +1,10 @@ import { integer, serial, text } from 'drizzle-orm/pg-core'; -import { collectiviteTable } from '../../collectivites/models/collectivite.models'; +import { collectiviteTable } from '../../collectivites/models/collectivite.table'; export const TagBase = { id: serial('id').primaryKey(), nom: text('nom').notNull(), - collectivite_id: integer('collectivite_id') + collectiviteId: integer('collectivite_id') .notNull() .references(() => collectiviteTable.id), }; diff --git a/backend/src/taxonomie/services/tag.service.ts b/backend/src/taxonomie/services/tag.service.ts new file mode 100644 index 0000000000..927060c25c --- /dev/null +++ b/backend/src/taxonomie/services/tag.service.ts @@ -0,0 +1,45 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { and, eq } from 'drizzle-orm'; +import DatabaseService from '../../common/services/database.service'; +import { partenaireTagTable } from '../models/partenaire-tag.table'; + +@Injectable() +export default class TagService { + private readonly logger = new Logger(TagService.name); + + constructor(private readonly databaseService: DatabaseService) {} + + /** + * TODO à factoriser avec les autres tags + * Récupère l'id du tag partenaire pour une collectivité et le crée s'il n'existe pas + * @param nom du partenaire + * @param collectiviteId identifiant de la collectivité + * @return identifiant du tag partenaire + */ + async getPartenaireId(nom: string, collectiviteId: number): Promise { + let tag = null; + if (collectiviteId) { + const tags = await this.databaseService.db + .select() + .from(partenaireTagTable) + .where( + and( + eq(partenaireTagTable.nom, nom.trim()), + eq(partenaireTagTable.collectiviteId, collectiviteId), + ), + ); + tag = tags.length > 0 ? tags[0] : null; + } + if (!tag) { + const toReturn = await this.databaseService.db + .insert(partenaireTagTable) + .values({ + collectiviteId: collectiviteId, + nom: nom, + }) + .returning(); + return toReturn[0]?.id; + } + return tag.id; + } +} From 7e59134dc4133d70c2cf41d45411cf6aea3ae6ab Mon Sep 17 00:00:00 2001 From: Amandine Date: Thu, 12 Sep 2024 18:24:44 +0200 Subject: [PATCH 04/22] =?UTF-8?q?Backend=20-=20Ajoute=20les=20th=C3=A9mati?= =?UTF-8?q?ques?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../taxonomie/models/sous-thematique.table.ts | 28 ++++++++++++++++++ .../src/taxonomie/models/thematique.table.ts | 22 ++++++++++++++ .../taxonomie/services/thematique.service.ts | 29 +++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 backend/src/taxonomie/models/sous-thematique.table.ts create mode 100644 backend/src/taxonomie/models/thematique.table.ts create mode 100644 backend/src/taxonomie/services/thematique.service.ts diff --git a/backend/src/taxonomie/models/sous-thematique.table.ts b/backend/src/taxonomie/models/sous-thematique.table.ts new file mode 100644 index 0000000000..a7031db51b --- /dev/null +++ b/backend/src/taxonomie/models/sous-thematique.table.ts @@ -0,0 +1,28 @@ +import { + integer, + pgTable, + serial, + text, + uniqueIndex, +} from 'drizzle-orm/pg-core'; +import { InferSelectModel } from 'drizzle-orm'; +import { thematiqueTable } from './thematique.table'; + +export const sousThematiqueTable = pgTable( + 'sous_thematique', + { + id: serial('id').primaryKey(), + thematiqueId: integer('thematique_id') + .notNull() + .references(() => thematiqueTable.id), + sousThematique: text('sous_thematique').notNull(), + }, + (table) => { + return { + sousThematiqueSousThematiqueThematiqueIdKey: uniqueIndex( + 'sous_thematique_sous_thematique_thematique_id_key ', + ).on(table.sousThematique, table.thematiqueId), + }; + }, +); +export type SousThematiqueType = InferSelectModel; diff --git a/backend/src/taxonomie/models/thematique.table.ts b/backend/src/taxonomie/models/thematique.table.ts new file mode 100644 index 0000000000..7cb290c822 --- /dev/null +++ b/backend/src/taxonomie/models/thematique.table.ts @@ -0,0 +1,22 @@ +import { InferSelectModel } from 'drizzle-orm'; +import { pgTable, serial, text, varchar } from 'drizzle-orm/pg-core'; +import { createSelectSchema } from 'drizzle-zod'; + +export const thematiqueTable = pgTable('thematique', { + id: serial('id').primaryKey(), + nom: text('nom').notNull(), + mdId: varchar('md_id'), +}); + +export type ThematiqueAvecAncienIdentifiantType = InferSelectModel< + typeof thematiqueTable +>; +export const thematiqueAvecAncienIdentifiantSchema = + createSelectSchema(thematiqueTable); + +export type ThematiqueType = Omit; + +export const thematiqueSchema = thematiqueAvecAncienIdentifiantSchema.pick({ + id: true, + nom: true, +}); diff --git a/backend/src/taxonomie/services/thematique.service.ts b/backend/src/taxonomie/services/thematique.service.ts new file mode 100644 index 0000000000..ff4ada0f83 --- /dev/null +++ b/backend/src/taxonomie/services/thematique.service.ts @@ -0,0 +1,29 @@ +import { Injectable, Logger } from '@nestjs/common'; +import DatabaseService from '../../common/services/database.service'; +import { + sousThematiqueTable, + SousThematiqueType, +} from '../models/sous-thematique.table'; + +@Injectable() +export default class ThematiqueService { + private readonly logger = new Logger(ThematiqueService.name); + + constructor(private readonly databaseService: DatabaseService) {} + + /** + * Récupère les sous thématiques provenant de la BDD + * @return une map de sous thématiques avec en clé le nom de la sous thématique + */ + async getSousThematiquesMap(): Promise> { + const result = await this.databaseService.db + .select() + .from(sousThematiqueTable); + const toReturn = new Map(); + for (let i = 0; i < result.length; i++) { + const thematique = result[i]; + toReturn.set(thematique.sousThematique, thematique); + } + return toReturn; + } +} From 174817ef4131e8b843047b2c5a92e65b3f30ec11 Mon Sep 17 00:00:00 2001 From: Amandine Date: Thu, 12 Sep 2024 18:26:31 +0200 Subject: [PATCH 05/22] Backend - Ajoute les fiches --- .../controllers/fiches-action.controller.ts | 2 +- .../models/fiche-action-action.table.ts | 21 +++ .../fiche-action-effet-attendu.table.ts | 18 +++ .../fiche-action-financeur-tag.table.ts | 17 ++ .../models/fiche-action-indicateur.table.ts | 18 +++ .../fiches/models/fiche-action-lien.table.ts | 15 ++ .../fiche-action-partenaire-tag.table.ts | 8 +- .../models/fiche-action-pilote.table.ts | 18 +-- .../models/fiche-action-referent.table.ts | 12 +- .../models/fiche-action-service-tag.table.ts | 18 +++ .../fiche-action-sous-thematique.table.ts | 18 +++ .../fiche-action-structure-tag.table.ts | 18 +++ .../models/fiche-action-thematique.table.ts | 16 ++ .../src/fiches/models/fiche-action.table.ts | 5 +- backend/src/fiches/services/fiche.service.ts | 149 ++++++++++++++++++ .../fiches-action-synthese.service.ts | 67 ++++---- 16 files changed, 366 insertions(+), 54 deletions(-) create mode 100644 backend/src/fiches/models/fiche-action-action.table.ts create mode 100644 backend/src/fiches/models/fiche-action-effet-attendu.table.ts create mode 100644 backend/src/fiches/models/fiche-action-financeur-tag.table.ts create mode 100644 backend/src/fiches/models/fiche-action-indicateur.table.ts create mode 100644 backend/src/fiches/models/fiche-action-lien.table.ts create mode 100644 backend/src/fiches/models/fiche-action-service-tag.table.ts create mode 100644 backend/src/fiches/models/fiche-action-sous-thematique.table.ts create mode 100644 backend/src/fiches/models/fiche-action-structure-tag.table.ts create mode 100644 backend/src/fiches/models/fiche-action-thematique.table.ts create mode 100644 backend/src/fiches/services/fiche.service.ts diff --git a/backend/src/fiches/controllers/fiches-action.controller.ts b/backend/src/fiches/controllers/fiches-action.controller.ts index e33b1915c5..351346fdf7 100644 --- a/backend/src/fiches/controllers/fiches-action.controller.ts +++ b/backend/src/fiches/controllers/fiches-action.controller.ts @@ -2,10 +2,10 @@ import { createZodDto } from '@anatine/zod-nestjs'; import { Controller, Get, Param, Query } from '@nestjs/common'; import { ApiOkResponse, ApiTags } from '@nestjs/swagger'; import { TokenInfo } from '../../auth/decorators/token-info.decorators'; -import type { SupabaseJwtPayload } from '../../auth/models/auth.models'; import { getFichesActionSyntheseSchema } from '../models/get-fiches-action-synthese.response'; import { getFichesActionFilterRequestSchema } from '../models/get-fiches-actions-filter.request'; import FichesActionSyntheseService from '../services/fiches-action-synthese.service'; +import type { SupabaseJwtPayload } from '../../auth/models/supabase-jwt.models'; /** * Création des classes de réponse à partir du schema pour générer automatiquement la documentation OpenAPI diff --git a/backend/src/fiches/models/fiche-action-action.table.ts b/backend/src/fiches/models/fiche-action-action.table.ts new file mode 100644 index 0000000000..b71f94554c --- /dev/null +++ b/backend/src/fiches/models/fiche-action-action.table.ts @@ -0,0 +1,21 @@ +import { + integer, + pgTable, + primaryKey, + varchar, +} from 'drizzle-orm/pg-core'; +import { actionRelationTable } from '../../referentiel/models/action-relation.table'; +import { ficheActionTable } from './fiche-action.table'; + +export const ficheActionActionTable = pgTable( + 'fiche_action_action', + { + ficheId: integer('fiche_id').references(() => ficheActionTable.id), + actionId: varchar('action_id').references(() => actionRelationTable.id), + }, + (table) => { + return { + pk: primaryKey({ columns: [table.ficheId, table.actionId] }), + }; + }, +); diff --git a/backend/src/fiches/models/fiche-action-effet-attendu.table.ts b/backend/src/fiches/models/fiche-action-effet-attendu.table.ts new file mode 100644 index 0000000000..998118357f --- /dev/null +++ b/backend/src/fiches/models/fiche-action-effet-attendu.table.ts @@ -0,0 +1,18 @@ +import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; +import { effetAttenduTable } from '../../taxonomie/models/effet-attendu.table'; +import { ficheActionTable } from './fiche-action.table'; + +export const ficheActionEffetAttenduTable = pgTable( + 'fiche_action_effet_attendu', + { + ficheId: integer('fiche_id').references(() => ficheActionTable.id), + effetAttenduId: integer('effet_attendu_id').references( + () => effetAttenduTable.id, + ), + }, + (table) => { + return { + pk: primaryKey({ columns: [table.ficheId, table.effetAttenduId] }), + }; + }, +); diff --git a/backend/src/fiches/models/fiche-action-financeur-tag.table.ts b/backend/src/fiches/models/fiche-action-financeur-tag.table.ts new file mode 100644 index 0000000000..0aedb5eec4 --- /dev/null +++ b/backend/src/fiches/models/fiche-action-financeur-tag.table.ts @@ -0,0 +1,17 @@ +import { integer, pgTable, serial } from 'drizzle-orm/pg-core'; +import { ficheActionTable } from './fiche-action.table'; +import { financeurTagTable } from '../../taxonomie/models/financeur-tag.table'; + +export const ficheActionFinanceurTagTable = pgTable( + 'fiche_action_financeur_tag', + { + id: serial('id').primaryKey(), + ficheId: integer('fiche_id') + .notNull() + .references(() => ficheActionTable.id), + financeurTagId: integer('financeur_tag_id').references( + () => financeurTagTable.id, + ), + montantTtc: integer('montant_ttc'), + }, +); diff --git a/backend/src/fiches/models/fiche-action-indicateur.table.ts b/backend/src/fiches/models/fiche-action-indicateur.table.ts new file mode 100644 index 0000000000..034f5b4db4 --- /dev/null +++ b/backend/src/fiches/models/fiche-action-indicateur.table.ts @@ -0,0 +1,18 @@ +import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; +import { indicateurDefinitionTable } from '../../indicateurs/models/indicateur-definition.table'; +import { ficheActionTable } from './fiche-action.table'; + +export const ficheActionIndicateurTable = pgTable( + 'fiche_action_indicateur', + { + ficheId: integer('fiche_id').references(() => ficheActionTable.id), + indicateurId: integer('indicateur_id').references( + () => indicateurDefinitionTable.id, + ), + }, + (table) => { + return { + pk: primaryKey({ columns: [table.ficheId, table.indicateurId] }), + }; + }, +); diff --git a/backend/src/fiches/models/fiche-action-lien.table.ts b/backend/src/fiches/models/fiche-action-lien.table.ts new file mode 100644 index 0000000000..5dcea8328f --- /dev/null +++ b/backend/src/fiches/models/fiche-action-lien.table.ts @@ -0,0 +1,15 @@ +import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; +import { ficheActionTable } from './fiche-action.table'; + +export const ficheActionLienTable = pgTable( + 'fiche_action_lien', + { + ficheUne: integer('fiche_une').references(() => ficheActionTable.id), + ficheDeux: integer('fiche_deux').references(() => ficheActionTable.id), + }, + (table) => { + return { + pk: primaryKey({ columns: [table.ficheUne, table.ficheDeux] }), + }; + }, +); diff --git a/backend/src/fiches/models/fiche-action-partenaire-tag.table.ts b/backend/src/fiches/models/fiche-action-partenaire-tag.table.ts index 65ee5db83e..a41180c0eb 100644 --- a/backend/src/fiches/models/fiche-action-partenaire-tag.table.ts +++ b/backend/src/fiches/models/fiche-action-partenaire-tag.table.ts @@ -1,18 +1,18 @@ import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; -import { partenaireTagTable } from '../../taxonomie/models/partenaire-tag.table'; import { ficheActionTable } from './fiche-action.table'; +import { partenaireTagTable } from '../../taxonomie/models/partenaire-tag.table'; export const ficheActionPartenaireTagTable = pgTable( 'fiche_action_partenaire_tag', { - fiche_id: integer('fiche_id').references(() => ficheActionTable.id), - partenaire_tag_id: integer('partenaire_tag_id').references( + ficheId: integer('fiche_id').references(() => ficheActionTable.id), + partenaireTagId: integer('partenaire_tag_id').references( () => partenaireTagTable.id, ), }, (table) => { return { - pk: primaryKey({ columns: [table.fiche_id, table.partenaire_tag_id] }), + pk: primaryKey({ columns: [table.ficheId, table.partenaireTagId] }), }; }, ); diff --git a/backend/src/fiches/models/fiche-action-pilote.table.ts b/backend/src/fiches/models/fiche-action-pilote.table.ts index 27e4dc481e..834ab11256 100644 --- a/backend/src/fiches/models/fiche-action-pilote.table.ts +++ b/backend/src/fiches/models/fiche-action-pilote.table.ts @@ -5,19 +5,19 @@ import { ficheActionTable } from './fiche-action.table'; export const ficheActionPiloteTable = pgTable( 'fiche_action_pilote', { - fiche_id: integer('fiche_id').references(() => ficheActionTable.id), - tag_id: integer('tag_id').references(() => personneTagTable.id), - user_id: uuid('user_id'), // references dcp + ficheId: integer('fiche_id').references(() => ficheActionTable.id), + tagId: integer('tag_id').references(() => personneTagTable.id), + userId: uuid('user_id'), // references dcp }, (table) => { return { - one_user_per_fiche: uniqueIndex('one_user_per_fiche ').on( - table.fiche_id, - table.user_id, + oneUserPerFiche: uniqueIndex('one_user_per_fiche ').on( + table.ficheId, + table.userId, ), - one_tag_per_fiche: uniqueIndex('one_tag_per_fiche ').on( - table.fiche_id, - table.tag_id, + oneTagPerFiche: uniqueIndex('one_tag_per_fiche ').on( + table.ficheId, + table.tagId, ), }; }, diff --git a/backend/src/fiches/models/fiche-action-referent.table.ts b/backend/src/fiches/models/fiche-action-referent.table.ts index f180ba4362..5bab23559b 100644 --- a/backend/src/fiches/models/fiche-action-referent.table.ts +++ b/backend/src/fiches/models/fiche-action-referent.table.ts @@ -1,19 +1,19 @@ import { integer, pgTable, uniqueIndex, uuid } from 'drizzle-orm/pg-core'; -import { personneTagTable } from '../../taxonomie/models/personne-tag.table'; import { ficheActionTable } from './fiche-action.table'; +import { personneTagTable } from '../../taxonomie/models/personne-tag.table'; export const ficheActionReferentTable = pgTable( 'fiche_action_referent', { - fiche_id: integer('fiche_id').references(() => ficheActionTable.id), - tag_id: integer('tag_id').references(() => personneTagTable.id), - user_id: uuid('user_id'), // references dcp + ficheId: integer('fiche_id').references(() => ficheActionTable.id), + tagId: integer('tag_id').references(() => personneTagTable.id), + userId: uuid('user_id'), // references dcp }, (table) => { return { - fiche_action_referent_fiche_id_user_id_tag_id_key: uniqueIndex( + ficheActionReferentFicheIdUserIdTagIdKey: uniqueIndex( 'fiche_action_referent_fiche_id_user_id_tag_id_key ', - ).on(table.fiche_id, table.user_id, table.tag_id), + ).on(table.ficheId, table.userId, table.tagId), }; }, ); diff --git a/backend/src/fiches/models/fiche-action-service-tag.table.ts b/backend/src/fiches/models/fiche-action-service-tag.table.ts new file mode 100644 index 0000000000..b1053354b6 --- /dev/null +++ b/backend/src/fiches/models/fiche-action-service-tag.table.ts @@ -0,0 +1,18 @@ +import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; +import { ficheActionTable } from './fiche-action.table'; +import { serviceTagTable } from '../../taxonomie/models/service-tag.table'; + +export const ficheActionServiceTagTable = pgTable( + 'fiche_action_service_tag', + { + ficheId: integer('fiche_id').references(() => ficheActionTable.id), + serviceTagId: integer('service_tag_id').references( + () => serviceTagTable.id, + ), + }, + (table) => { + return { + pk: primaryKey({ columns: [table.ficheId, table.serviceTagId] }), + }; + }, +); diff --git a/backend/src/fiches/models/fiche-action-sous-thematique.table.ts b/backend/src/fiches/models/fiche-action-sous-thematique.table.ts new file mode 100644 index 0000000000..886c0e97c0 --- /dev/null +++ b/backend/src/fiches/models/fiche-action-sous-thematique.table.ts @@ -0,0 +1,18 @@ +import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; +import { ficheActionTable } from './fiche-action.table'; +import { sousThematiqueTable } from '../../taxonomie/models/sous-thematique.table'; + +export const ficheActionSousThematiqueTable = pgTable( + 'fiche_action_sous_thematique', + { + ficheId: integer('fiche_id').references(() => ficheActionTable.id), + thematiqueId: integer('thematique_id').references( + () => sousThematiqueTable.id, + ), + }, + (table) => { + return { + pk: primaryKey({ columns: [table.ficheId, table.thematiqueId] }), + }; + }, +); diff --git a/backend/src/fiches/models/fiche-action-structure-tag.table.ts b/backend/src/fiches/models/fiche-action-structure-tag.table.ts new file mode 100644 index 0000000000..19bdd044b0 --- /dev/null +++ b/backend/src/fiches/models/fiche-action-structure-tag.table.ts @@ -0,0 +1,18 @@ +import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; +import { ficheActionTable } from './fiche-action.table'; +import { structureTagTable } from '../../taxonomie/models/structure-tag.table'; + +export const ficheActionStructureTagTable = pgTable( + 'fiche_action_structure_tag', + { + ficheId: integer('fiche_id').references(() => ficheActionTable.id), + structureTagId: integer('structure_tag_id').references( + () => structureTagTable.id, + ), + }, + (table) => { + return { + pk: primaryKey({ columns: [table.ficheId, table.structureTagId] }), + }; + }, +); diff --git a/backend/src/fiches/models/fiche-action-thematique.table.ts b/backend/src/fiches/models/fiche-action-thematique.table.ts new file mode 100644 index 0000000000..c15676e982 --- /dev/null +++ b/backend/src/fiches/models/fiche-action-thematique.table.ts @@ -0,0 +1,16 @@ +import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; +import { thematiqueTable } from '../../taxonomie/models/thematique.table'; +import { ficheActionTable } from './fiche-action.table'; + +export const ficheActionThematiqueTable = pgTable( + 'fiche_action_thematique', + { + ficheId: integer('fiche_id').references(() => ficheActionTable.id), + thematiqueId: integer('thematique_id').references(() => thematiqueTable.id), + }, + (table) => { + return { + pk: primaryKey({ columns: [table.ficheId, table.thematiqueId] }), + }; + }, +); diff --git a/backend/src/fiches/models/fiche-action.table.ts b/backend/src/fiches/models/fiche-action.table.ts index 7c0d7dddce..6fb19bdb46 100644 --- a/backend/src/fiches/models/fiche-action.table.ts +++ b/backend/src/fiches/models/fiche-action.table.ts @@ -11,6 +11,7 @@ import { uuid, varchar, } from 'drizzle-orm/pg-core'; +import { collectiviteTable } from '../../collectivites/models/collectivite.table'; export const ficheActionPiliersEciEnum = pgEnum('fiche_action_piliers_eci', [ 'Approvisionnement durable', @@ -124,7 +125,9 @@ export const ficheActionTable = pgTable('fiche_action', { calendrier: varchar('calendrier', { length: 10000 }), notesComplementaires: varchar('notes_complementaires', { length: 20000 }), majTermine: boolean('maj_termine'), - collectiviteId: integer('collectivite_id').notNull(), + collectiviteId: integer('collectivite_id') + .notNull() + .references(() => collectiviteTable.id), createdAt: timestamp('created_at', { withTimezone: true, mode: 'string' }) .default(sql`CURRENT_TIMESTAMP`) .notNull(), diff --git a/backend/src/fiches/services/fiche.service.ts b/backend/src/fiches/services/fiche.service.ts new file mode 100644 index 0000000000..9c4dd31030 --- /dev/null +++ b/backend/src/fiches/services/fiche.service.ts @@ -0,0 +1,149 @@ +import { Injectable, Logger } from '@nestjs/common'; +import DatabaseService from '../../common/services/database.service'; +import { + CreateFicheActionType, + ficheActionTable, +} from '../models/fiche-action.table'; +import TagService from '../../taxonomie/services/tag.service'; +import { actionImpactFicheActionTable } from '../models/action-impact-fiche-action.table'; +import { ficheActionActionTable } from '../models/fiche-action-action.table'; +import { ficheActionPartenaireTagTable } from '../models/fiche-action-partenaire-tag.table'; +import { ficheActionEffetAttenduTable } from '../models/fiche-action-effet-attendu.table'; +import { ficheActionIndicateurTable } from '../models/fiche-action-indicateur.table'; +import { ficheActionSousThematiqueTable } from '../models/fiche-action-sous-thematique.table'; +import { ficheActionThematiqueTable } from '../models/fiche-action-thematique.table'; + +@Injectable() +export default class FicheService { + private readonly logger = new Logger(FicheService.name); + + constructor( + private readonly databaseService: DatabaseService, + private readonly tagService: TagService, + ) {} + + /** + * Crée une fiche action + * @param fiche + * @return identifiant de la fiche crée + */ + async createFiche(fiche: CreateFicheActionType): Promise { + this.logger.log( + `Création de la fiche ${fiche.titre} pour la collectivité ${fiche.collectiviteId}`, + ); + const ficheCree = await this.databaseService.db + .insert(ficheActionTable) + .values(fiche) + .returning(); + return ficheCree[0]?.id; + } + + /** + * Ajoute une thématique à une fiche + * @param ficheId identifiant de la fiche + * @param thematiqueId identifiant de la thématique + */ + async addThematique(ficheId: number, thematiqueId: number): Promise { + await this.databaseService.db.insert(ficheActionThematiqueTable).values({ + ficheId: ficheId, + thematiqueId: thematiqueId, + }); + } + + /** + * Ajoute une sous-thématique à une fiche + * @param ficheId identifiant de la fiche + * @param thematiqueId identifiant de la sous-thématique + */ + async addSousThematique( + ficheId: number, + thematiqueId: number, + ): Promise { + await this.databaseService.db + .insert(ficheActionSousThematiqueTable) + .values({ + ficheId: ficheId, + thematiqueId: thematiqueId, + }); + } + + /** + * Ajoute un indicateur à une fiche + * @param ficheId identifiant de la fiche + * @param indicateurId identifiant de l'indicateur + */ + async addIndicateur(ficheId: number, indicateurId: number): Promise { + await this.databaseService.db.insert(ficheActionIndicateurTable).values({ + ficheId: ficheId, + indicateurId: indicateurId, + }); + } + + /** + * Ajoute un effet attendu à une fiche + * @param ficheId identifiant de la fiche + * @param effetAttenduId identifiant de l'effet + */ + async addEffetAttendu( + ficheId: number, + effetAttenduId: number, + ): Promise { + await this.databaseService.db.insert(ficheActionEffetAttenduTable).values({ + ficheId: ficheId, + effetAttenduId: effetAttenduId, + }); + } + + /** + * Ajoute un partenaire à une fiche à partir de l'id du tag + * @param ficheId identifiant de la fiche + * @param tagId identifiant du partenaire + */ + async addPartenaireById(ficheId: number, tagId: number): Promise { + await this.databaseService.db.insert(ficheActionPartenaireTagTable).values({ + ficheId: ficheId, + partenaireTagId: tagId, + }); + } + + /** + * Ajoute un partenaire à une fiche à partir du nom du partenaire et la collectivité + * @param ficheId identifiant de la fiche + * @param nomTag nom du partenaire + * @param collectiviteId identifiant de la collectivité + */ + async addPartenaireByNom( + ficheId: number, + nomTag: string, + collectiviteId: number, + ): Promise { + const tagId = await this.tagService.getPartenaireId(nomTag, collectiviteId); + await this.addPartenaireById(ficheId, tagId); + } + + // On ajoute le financement + + /** + * Ajoute une action du référentiel à une fiche + * @param ficheId identifiant de la fiche + * @param actionId identifiant de l'action + */ + async addActionReferentiel(ficheId: number, actionId: string): Promise { + await this.databaseService.db.insert(ficheActionActionTable).values({ + ficheId: ficheId, + actionId: actionId, + }); + } + + /** + * Ajoute une action à impact à une fiche + * @param ficheId identifiant de la fiche + * @param actionId identifiant de l'action + */ + async addActionImpact(ficheId: number, actionId: number): Promise { + await this.databaseService.db.insert(actionImpactFicheActionTable).values({ + ficheId: ficheId, + actionImpactId: actionId, + }); + } +} diff --git a/backend/src/fiches/services/fiches-action-synthese.service.ts b/backend/src/fiches/services/fiches-action-synthese.service.ts index c05a611988..de3c3be705 100644 --- a/backend/src/fiches/services/fiches-action-synthese.service.ts +++ b/backend/src/fiches/services/fiches-action-synthese.service.ts @@ -12,7 +12,6 @@ import { SQLWrapper, } from 'drizzle-orm'; import { PgColumn } from 'drizzle-orm/pg-core'; -import { NiveauAcces, SupabaseJwtPayload } from '../../auth/models/auth.models'; import { AuthService } from '../../auth/services/auth.service'; import { CountSyntheseType } from '../../common/models/count-synthese.dto'; import { getModifiedSinceDate } from '../../common/models/modified-since.enum'; @@ -29,6 +28,8 @@ import { } from '../models/fiche-action.table'; import { GetFichesActionSyntheseResponseType } from '../models/get-fiches-action-synthese.response'; import { GetFichesActionFilterRequestType } from '../models/get-fiches-actions-filter.request'; +import { NiveauAcces } from '../../auth/models/private-utilisateur-droit.table'; +import { SupabaseJwtPayload } from '../../auth/models/supabase-jwt.models'; @Injectable() export default class FichesActionSyntheseService { @@ -41,13 +42,13 @@ export default class FichesActionSyntheseService { constructor( private readonly databaseService: DatabaseService, - private readonly authService: AuthService + private readonly authService: AuthService, ) {} async getFichesActionSynthese( collectiviteId: number, filter: GetFichesActionFilterRequestType, - tokenInfo: SupabaseJwtPayload + tokenInfo: SupabaseJwtPayload, ): Promise { this.logger.log( `Récupération de la synthese des fiches action pour la collectivité ${collectiviteId}: filtre ${JSON.stringify( @@ -73,27 +74,27 @@ export default class FichesActionSyntheseService { getFicheActionPartenaireTagsQuery() { return this.databaseService.db .select({ - fiche_id: ficheActionPartenaireTagTable.fiche_id, + fiche_id: ficheActionPartenaireTagTable.ficheId, partenaire_tag_ids: - sql`array_agg(${ficheActionPartenaireTagTable.partenaire_tag_id})`.as( - this.FICHE_ACTION_PARTENAIRE_TAGS_QUERY_FIELD + sql`array_agg(${ficheActionPartenaireTagTable.partenaireTagId})`.as( + this.FICHE_ACTION_PARTENAIRE_TAGS_QUERY_FIELD, ), }) .from(ficheActionPartenaireTagTable) - .groupBy(ficheActionPartenaireTagTable.fiche_id) + .groupBy(ficheActionPartenaireTagTable.ficheId) .as(this.FICHE_ACTION_PARTENAIRE_TAGS_QUERY_ALIAS); } getFicheActionAxesQuery() { return this.databaseService.db .select({ - fiche_id: ficheActionAxeTable.fiche_id, - axe_ids: sql`array_agg(${ficheActionAxeTable.axe_id})`.as('axe_ids'), + fiche_id: ficheActionAxeTable.ficheId, + axe_ids: sql`array_agg(${ficheActionAxeTable.axeId})`.as('axe_ids'), plan_ids: sql`array_agg(${axeTable.plan})`.as('plan_ids'), }) .from(ficheActionAxeTable) - .leftJoin(axeTable, eq(axeTable.id, ficheActionAxeTable.axe_id)) - .groupBy(ficheActionAxeTable.fiche_id) + .leftJoin(axeTable, eq(axeTable.id, ficheActionAxeTable.axeId)) + .groupBy(ficheActionAxeTable.ficheId) .as('ficheActionAxes'); } @@ -103,7 +104,7 @@ export default class FichesActionSyntheseService { fiche_id: ficheActionServiceTagTable.fiche_id, service_tag_ids: sql`array_agg(${ficheActionServiceTagTable.service_tag_id})`.as( - 'service_tag_ids' + 'service_tag_ids', ), }) .from(ficheActionServiceTagTable) @@ -114,25 +115,25 @@ export default class FichesActionSyntheseService { getFicheActionPilotesQuery() { return this.databaseService.db .select({ - fiche_id: ficheActionPiloteTable.fiche_id, + fiche_id: ficheActionPiloteTable.ficheId, pilote_user_ids: - sql`array_remove(array_agg(${ficheActionPiloteTable.user_id}), NULL)`.as( - 'pilote_user_ids' + sql`array_remove(array_agg(${ficheActionPiloteTable.userId}), NULL)`.as( + 'pilote_user_ids', ), pilote_tag_ids: - sql`array_remove(array_agg(${ficheActionPiloteTable.tag_id}), NULL)`.as( - 'pilote_tag_ids' + sql`array_remove(array_agg(${ficheActionPiloteTable.tagId}), NULL)`.as( + 'pilote_tag_ids', ), }) .from(ficheActionPiloteTable) - .groupBy(ficheActionPiloteTable.fiche_id) + .groupBy(ficheActionPiloteTable.ficheId) .as('ficheActionPilotes'); } async getFichesAction( collectiviteId: number, filter: GetFichesActionFilterRequestType, - tokenInfo: SupabaseJwtPayload + tokenInfo: SupabaseJwtPayload, ): Promise { this.logger.log( `Récupération des fiches action pour la collectivité ${collectiviteId}: filtre ${JSON.stringify( @@ -160,19 +161,19 @@ export default class FichesActionSyntheseService { .from(ficheActionTable) .leftJoin( ficheActionPartenaireTags, - eq(ficheActionPartenaireTags.fiche_id, ficheActionTable.id) + eq(ficheActionPartenaireTags.fiche_id, ficheActionTable.id), ) .leftJoin( ficheActionPilotes, - eq(ficheActionPilotes.fiche_id, ficheActionTable.id) + eq(ficheActionPilotes.fiche_id, ficheActionTable.id), ) .leftJoin( ficheActionServiceTags, - eq(ficheActionServiceTags.fiche_id, ficheActionTable.id) + eq(ficheActionServiceTags.fiche_id, ficheActionTable.id), ) .leftJoin( ficheActionAxes, - eq(ficheActionAxes.fiche_id, ficheActionTable.id) + eq(ficheActionAxes.fiche_id, ficheActionTable.id), ) .where(and(...conditions)); @@ -181,7 +182,7 @@ export default class FichesActionSyntheseService { getConditions( collectiviteId: number, - filter: GetFichesActionFilterRequestType + filter: GetFichesActionFilterRequestType, ): (SQLWrapper | SQL)[] { const conditions: (SQLWrapper | SQL)[] = [ eq(ficheActionTable.collectiviteId, collectiviteId), @@ -192,7 +193,7 @@ export default class FichesActionSyntheseService { if (filter.modified_since) { const modifiedSinceDate = getModifiedSinceDate(filter.modified_since); conditions.push( - gte(ficheActionTable.modifiedAt, modifiedSinceDate.toISOString()) + gte(ficheActionTable.modifiedAt, modifiedSinceDate.toISOString()), ); } if (filter.modified_after) { @@ -202,14 +203,14 @@ export default class FichesActionSyntheseService { // Vraiment étrange, probable bug de drizzle, on le peut pas lui donner le tableau directement const sqlNumberArray = `{${filter.partenaire_tag_ids.join(',')}}`; conditions.push( - arrayOverlaps(sql`partenaire_tag_ids`, sql`${sqlNumberArray}`) + arrayOverlaps(sql`partenaire_tag_ids`, sql`${sqlNumberArray}`), ); } if (filter.service_tag_ids?.length) { // Vraiment étrange, probable bug de drizzle, on le peut pas lui donner le tableau directement const sqlNumberArray = `{${filter.service_tag_ids.join(',')}}`; conditions.push( - arrayOverlaps(sql`service_tag_ids`, sql`${sqlNumberArray}`) + arrayOverlaps(sql`service_tag_ids`, sql`${sqlNumberArray}`), ); } if (filter.plan_ids?.length) { @@ -222,13 +223,13 @@ export default class FichesActionSyntheseService { if (filter.pilote_user_ids?.length) { const sqlNumberArray = `{${filter.pilote_user_ids.join(',')}}`; piloteConditions.push( - arrayOverlaps(sql`pilote_user_ids`, sql`${sqlNumberArray}`) + arrayOverlaps(sql`pilote_user_ids`, sql`${sqlNumberArray}`), ); } if (filter.pilote_tag_ids?.length) { const sqlNumberArray = `{${filter.pilote_tag_ids.join(',')}}`; piloteConditions.push( - arrayOverlaps(sql`pilote_tag_ids`, sql`${sqlNumberArray}`) + arrayOverlaps(sql`pilote_tag_ids`, sql`${sqlNumberArray}`), ); } if (piloteConditions.length) { @@ -265,19 +266,19 @@ export default class FichesActionSyntheseService { .from(ficheActionTable) .leftJoin( ficheActionPartenaireTags, - eq(ficheActionPartenaireTags.fiche_id, ficheActionTable.id) + eq(ficheActionPartenaireTags.fiche_id, ficheActionTable.id), ) .leftJoin( ficheActionPilotes, - eq(ficheActionPilotes.fiche_id, ficheActionTable.id) + eq(ficheActionPilotes.fiche_id, ficheActionTable.id), ) .leftJoin( ficheActionServiceTags, - eq(ficheActionServiceTags.fiche_id, ficheActionTable.id) + eq(ficheActionServiceTags.fiche_id, ficheActionTable.id), ) .leftJoin( ficheActionAxes, - eq(ficheActionAxes.fiche_id, ficheActionTable.id) + eq(ficheActionAxes.fiche_id, ficheActionTable.id), ) .where(and(...conditions)) .groupBy(propriete); From 37fd1780a8b11c68af628dce4b5c5374c92fe8ef Mon Sep 17 00:00:00 2001 From: Amandine Date: Thu, 12 Sep 2024 18:26:46 +0200 Subject: [PATCH 06/22] Backend - Ajoute les axes --- backend/src/fiches/models/axe.table.ts | 19 ++--- .../fiches/models/fiche-action-axe.table.ts | 8 +-- .../plan-action-type-categorie.table.ts | 8 +++ .../fiches/models/plan-action-type.table.ts | 4 +- backend/src/fiches/services/axe.service.ts | 70 +++++++++++++++++++ 5 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 backend/src/fiches/models/plan-action-type-categorie.table.ts create mode 100644 backend/src/fiches/services/axe.service.ts diff --git a/backend/src/fiches/models/axe.table.ts b/backend/src/fiches/models/axe.table.ts index 11ad2595a1..665cd9fa1a 100644 --- a/backend/src/fiches/models/axe.table.ts +++ b/backend/src/fiches/models/axe.table.ts @@ -8,25 +8,26 @@ import { timestamp, uuid, } from 'drizzle-orm/pg-core'; -import { collectiviteTable } from '../../collectivites/models/collectivite.models'; +import { collectiviteTable } from '../../collectivites/models/collectivite.table'; +import { panierTable } from '../../panier/models/panier.table'; import { planActionTypeTable } from './plan-action-type.table'; -export const axeTable = pgTable('axe', { +export const axeTable: ReturnType = pgTable('axe', { id: serial('id').primaryKey(), nom: text('nom'), - collectivite_id: integer('collectivite_id') + collectiviteId: integer('collectivite_id') .notNull() .references(() => collectiviteTable.id), - parent: integer('parent').references((): AnyPgColumn => axeTable.id), - plan: integer('plan').references((): AnyPgColumn => axeTable.id), + parent: integer('parent').references(() => axeTable.id), + plan: integer('plan').references(() => axeTable.id), type: integer('type').references(() => planActionTypeTable.id), - created_at: timestamp('created_at', { withTimezone: true }) + createdAt: timestamp('created_at', { withTimezone: true }) .notNull() .defaultNow(), - modified_at: timestamp('modified_at', { withTimezone: true }) + modifiedAt: timestamp('modified_at', { withTimezone: true }) .notNull() .defaultNow(), - modified_by: uuid('modified_by'), // TODO references auth.uid - panier_id: integer('panier_id'), // TODO references panier + modifiedBy: uuid('modified_by'), // TODO references auth.uid + panierId: integer('panier_id').references(() => panierTable.id), }); export type CreateAxeType = InferInsertModel; diff --git a/backend/src/fiches/models/fiche-action-axe.table.ts b/backend/src/fiches/models/fiche-action-axe.table.ts index 3fe9abe079..b924e38011 100644 --- a/backend/src/fiches/models/fiche-action-axe.table.ts +++ b/backend/src/fiches/models/fiche-action-axe.table.ts @@ -1,16 +1,16 @@ import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; -import { axeTable } from './axe.table'; import { ficheActionTable } from './fiche-action.table'; +import { axeTable } from './axe.table'; export const ficheActionAxeTable = pgTable( 'fiche_action_axe', { - fiche_id: integer('fiche_id').references(() => ficheActionTable.id), - axe_id: integer('axe_id').references(() => axeTable.id), + ficheId: integer('fiche_id').references(() => ficheActionTable.id), + axeId: integer('axe_id').references(() => axeTable.id), }, (table) => { return { - pk: primaryKey({ columns: [table.fiche_id, table.axe_id] }), + pk: primaryKey({ columns: [table.ficheId, table.axeId] }), }; }, ); diff --git a/backend/src/fiches/models/plan-action-type-categorie.table.ts b/backend/src/fiches/models/plan-action-type-categorie.table.ts new file mode 100644 index 0000000000..c29ee7c46c --- /dev/null +++ b/backend/src/fiches/models/plan-action-type-categorie.table.ts @@ -0,0 +1,8 @@ +import { pgTable, text } from 'drizzle-orm/pg-core'; + +export const planActionTypeCategorieTable = pgTable( + 'plan_action_type_categorie', + { + categorie: text('categorie').primaryKey(), + }, +); diff --git a/backend/src/fiches/models/plan-action-type.table.ts b/backend/src/fiches/models/plan-action-type.table.ts index 3ee96b6acb..530457b810 100644 --- a/backend/src/fiches/models/plan-action-type.table.ts +++ b/backend/src/fiches/models/plan-action-type.table.ts @@ -1,5 +1,5 @@ import { pgTable, serial, text, uniqueIndex } from 'drizzle-orm/pg-core'; -import { planActionTypeCategorieTable } from './plan-action-type-category.table'; +import { planActionTypeCategorieTable } from './plan-action-type-categorie.table'; export const planActionTypeTable = pgTable( 'plan_action_type', @@ -13,7 +13,7 @@ export const planActionTypeTable = pgTable( }, (table) => { return { - plan_action_type_categorie_type_key: uniqueIndex( + planActionTypeCategorieTypeKey: uniqueIndex( 'plan_action_type_categorie_type_key', ).on(table.categorie, table.type), }; diff --git a/backend/src/fiches/services/axe.service.ts b/backend/src/fiches/services/axe.service.ts new file mode 100644 index 0000000000..25930b8e35 --- /dev/null +++ b/backend/src/fiches/services/axe.service.ts @@ -0,0 +1,70 @@ +import { Injectable, Logger } from '@nestjs/common'; +import DatabaseService from '../../common/services/database.service'; +import { and, eq, isNull, or } from 'drizzle-orm'; +import { axeTable, CreateAxeType } from '../models/axe.table'; +import { ficheActionAxeTable } from '../models/fiche-action-axe.table'; + +@Injectable() +export default class AxeService { + private readonly logger = new Logger(AxeService.name); + + constructor(private readonly databaseService: DatabaseService) {} + + /** + * Crée un axe + * @param axe + * @return identifiant de l'axe créé + */ + async createAxe(axe: CreateAxeType): Promise { + this.logger.log( + `Création de l'axe ${axe.nom} pour la collectivité ${axe.collectiviteId}`, + ); + const axeCree = await this.databaseService.db + .insert(axeTable) + .values(axe) + .returning(); + return axeCree[0]?.id; + } + + /** + * Retourne l'identifiant d'un axe s'il existe déjà ou le crée + * Un axe existe déjà si : même nom, même collectivité, et même axe parent + * @param axe + * @return identifiant de l'axe récupéré ou créé + */ + async createOrReturnAxeId(axe: CreateAxeType): Promise { + const axeExistants = await this.databaseService.db + .select() + .from(axeTable) + .where( + and( + eq(axeTable.nom, axe.nom.trim()), + eq(axeTable.collectiviteId, axe.collectiviteId), + or( + and( + isNull(axeTable.parent), + isNull(axe.parent ? axe.parent : null), + ), + eq(axeTable.parent, axe.parent), + ), + ), + ); + const axeExistant = axeExistants?.length > 0 ? axeExistants[0] : null; + if (!axeExistant) { + return await this.createAxe(axe); + } + return axeExistant.id; + } + + /** + * Ajoute une fiche dans un axe + * @param ficheId identifiant de la fiche + * @param axeId identifiant de l'axe + */ + async addFicheAction(ficheId: number, axeId: number): Promise { + await this.databaseService.db.insert(ficheActionAxeTable).values({ + axeId: axeId, + ficheId: ficheId, + }); + } +} From a09e48296693bd219cf651198b9043d7670a539b Mon Sep 17 00:00:00 2001 From: Amandine Date: Thu, 12 Sep 2024 18:27:19 +0200 Subject: [PATCH 07/22] Backend - Ajoute les documents --- backend/src/documents/models/annexe.table.ts | 10 +++++ .../src/documents/models/document-lien.dto.ts | 18 +++++++++ .../documents/models/document.basetable.ts | 27 +++++++++++++ .../models/preuve-complementaire.table.ts | 10 +++++ .../documents/models/preuve-rapport.table.ts | 7 ++++ .../preuve-reglementaire-definition.table.ts | 10 +++++ .../models/preuve-reglementaire.table.ts | 10 +++++ .../documents/services/document.service.ts | 38 +++++++++++++++++++ 8 files changed, 130 insertions(+) create mode 100644 backend/src/documents/models/annexe.table.ts create mode 100644 backend/src/documents/models/document-lien.dto.ts create mode 100644 backend/src/documents/models/document.basetable.ts create mode 100644 backend/src/documents/models/preuve-complementaire.table.ts create mode 100644 backend/src/documents/models/preuve-rapport.table.ts create mode 100644 backend/src/documents/models/preuve-reglementaire-definition.table.ts create mode 100644 backend/src/documents/models/preuve-reglementaire.table.ts create mode 100644 backend/src/documents/services/document.service.ts diff --git a/backend/src/documents/models/annexe.table.ts b/backend/src/documents/models/annexe.table.ts new file mode 100644 index 0000000000..abf9fa5a6c --- /dev/null +++ b/backend/src/documents/models/annexe.table.ts @@ -0,0 +1,10 @@ +import { integer, pgTable } from 'drizzle-orm/pg-core'; +import { ficheActionTable } from '../../fiches/models/fiche-action.table'; +import { DocumentBase } from './document.basetable'; + +export const annexeTable = pgTable('annexe', { + ...DocumentBase, + ficheId: integer('fiche_id') + .notNull() + .references(() => ficheActionTable.id), +}); diff --git a/backend/src/documents/models/document-lien.dto.ts b/backend/src/documents/models/document-lien.dto.ts new file mode 100644 index 0000000000..6efcfcc37d --- /dev/null +++ b/backend/src/documents/models/document-lien.dto.ts @@ -0,0 +1,18 @@ +import { extendApi } from '@anatine/zod-openapi'; +import { z } from 'zod'; + +export type lienType = { + label: string; + url: string; +}; + +export const lienSchema = extendApi( + z + .object({ + label: z.string().openapi({ description: `Nom descriptif du lien` }), + url: z.string().openapi({ description: `URL du lien` }), + }) + .openapi({ + title: 'Un lien URL.', + }), +); \ No newline at end of file diff --git a/backend/src/documents/models/document.basetable.ts b/backend/src/documents/models/document.basetable.ts new file mode 100644 index 0000000000..a70c71a227 --- /dev/null +++ b/backend/src/documents/models/document.basetable.ts @@ -0,0 +1,27 @@ +import { + serial, + text, + integer, + timestamp, + uuid, + jsonb, +} from 'drizzle-orm/pg-core'; +import { collectiviteTable } from '../../collectivites/models/collectivite.table'; + +export const DocumentBase = { + id: serial('id').primaryKey(), + collectiviteId: integer('collectivite_id') + .notNull() + .references(() => collectiviteTable.id), + fichierId: integer('fichier_id'), // reference indirectement labellisation.bibliotheque_fichier + url: text('url'), + titre: text('titre'), + commentaire: text('commentaire'), + modifiedAt: timestamp('modified_at', { withTimezone: true }) + .notNull() + .defaultNow(), + modifiedBy: uuid('modified_by'), // TODO references auth.uid, + lien: jsonb('lien'), +}; + + diff --git a/backend/src/documents/models/preuve-complementaire.table.ts b/backend/src/documents/models/preuve-complementaire.table.ts new file mode 100644 index 0000000000..e4bbd24613 --- /dev/null +++ b/backend/src/documents/models/preuve-complementaire.table.ts @@ -0,0 +1,10 @@ +import { pgTable, text } from 'drizzle-orm/pg-core'; +import { actionRelationTable } from '../../referentiel/models/action-relation.table'; +import { DocumentBase } from './document.basetable'; + +export const preuveComplementaireTable = pgTable('preuve_complementaire', { + ...DocumentBase, + actionId: text('action_id') + .notNull() + .references(() => actionRelationTable.id), +}); diff --git a/backend/src/documents/models/preuve-rapport.table.ts b/backend/src/documents/models/preuve-rapport.table.ts new file mode 100644 index 0000000000..6cbb8e9397 --- /dev/null +++ b/backend/src/documents/models/preuve-rapport.table.ts @@ -0,0 +1,7 @@ +import { pgTable, timestamp } from 'drizzle-orm/pg-core'; +import { DocumentBase } from './document.basetable'; + +export const preuveRapportTable = pgTable('preuve_rapport', { + ...DocumentBase, + date: timestamp('date', { withTimezone: true }).notNull(), +}); diff --git a/backend/src/documents/models/preuve-reglementaire-definition.table.ts b/backend/src/documents/models/preuve-reglementaire-definition.table.ts new file mode 100644 index 0000000000..ba5a56bfbb --- /dev/null +++ b/backend/src/documents/models/preuve-reglementaire-definition.table.ts @@ -0,0 +1,10 @@ +import { pgTable, text, varchar } from 'drizzle-orm/pg-core'; + +export const preuveReglementaireDefinitionTable = pgTable( + 'preuve_reglementaire_definition', + { + id: varchar('id').primaryKey(), + nom: text('nom').notNull(), + description: text('description').notNull(), + }, +); diff --git a/backend/src/documents/models/preuve-reglementaire.table.ts b/backend/src/documents/models/preuve-reglementaire.table.ts new file mode 100644 index 0000000000..ed9a6b0511 --- /dev/null +++ b/backend/src/documents/models/preuve-reglementaire.table.ts @@ -0,0 +1,10 @@ +import { pgTable, varchar } from 'drizzle-orm/pg-core'; +import { DocumentBase } from './document.basetable'; +import { preuveReglementaireDefinitionTable } from './preuve-reglementaire-definition.table'; + +export const preuveReglementaireTable = pgTable('preuve_reglementaire', { + ...DocumentBase, + preuveId: varchar('preuve_id') + .notNull() + .references(() => preuveReglementaireDefinitionTable.id), +}); diff --git a/backend/src/documents/services/document.service.ts b/backend/src/documents/services/document.service.ts new file mode 100644 index 0000000000..7f44ad4f92 --- /dev/null +++ b/backend/src/documents/services/document.service.ts @@ -0,0 +1,38 @@ +import { Injectable, Logger } from '@nestjs/common'; +import DatabaseService from '../../common/services/database.service'; +import { annexeTable } from '../models/annexe.table'; +import { lienType } from '../models/document-lien.dto'; + +@Injectable() +export default class DocumentService { + private readonly logger = new Logger(DocumentService.name); + + constructor(private readonly databaseService: DatabaseService) {} + + /** + * Crée une annexe de type lien // TODO refaire pour inclure les documents + * @param ficheId identifiant de la fiche + * @param lien label et url du lien + * @param collectiviteId identifiant de la collectivité concernée + * @return identifiant de la fiche crée + */ + async createLienAnnexe( + ficheId: number, + lien: lienType, + collectiviteId: number, + ): Promise { + this.logger.log( + `Création de l'annexe ${lien.label} pour la collectivité ${collectiviteId}`, + ); + const annexeCree = await this.databaseService.db + .insert(annexeTable) + .values({ + collectiviteId: collectiviteId, + url: lien.url, + titre: lien.label, + ficheId: ficheId, + }) + .returning(); + return annexeCree[0]?.id; + } +} From e179931ea835d403b2fd5d236f113c5b8a592fa8 Mon Sep 17 00:00:00 2001 From: Amandine Date: Thu, 12 Sep 2024 18:27:59 +0200 Subject: [PATCH 08/22] =?UTF-8?q?Backend=20-=20Ajoute=20les=20actions=20de?= =?UTF-8?q?s=20r=C3=A9f=C3=A9rentiels?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../models/action-definition.table.ts | 16 +++++------ .../models/action-relation.table.ts | 27 +++++++++++++++++++ 2 files changed, 35 insertions(+), 8 deletions(-) rename backend/src/{referentiels => referentiel}/models/action-definition.table.ts (83%) create mode 100644 backend/src/referentiel/models/action-relation.table.ts diff --git a/backend/src/referentiels/models/action-definition.table.ts b/backend/src/referentiel/models/action-definition.table.ts similarity index 83% rename from backend/src/referentiels/models/action-definition.table.ts rename to backend/src/referentiel/models/action-definition.table.ts index 993e2b4f39..7544aab123 100644 --- a/backend/src/referentiels/models/action-definition.table.ts +++ b/backend/src/referentiel/models/action-definition.table.ts @@ -18,14 +18,14 @@ export const actionCategorieEnum = pgEnum('action_categorie', [ ]); export const actionIdVarchar = varchar('action_id', { length: 30 }); export const actionIdReference = actionIdVarchar.references( - () => actionDefinitionTable.action_id, + () => actionDefinitionTable.actionId, ); export const actionDefinitionTable = pgTable('action_definition', { - modified_at: timestamp('modified_at', { withTimezone: true, mode: 'string' }) + modifiedAt: timestamp('modified_at', { withTimezone: true, mode: 'string' }) .default(sql`CURRENT_TIMESTAMP`) .notNull(), - action_id: actionIdVarchar.primaryKey().notNull(), + actionId: actionIdVarchar.primaryKey().notNull(), referentiel: referentielEnum('referentiel').notNull(), identifiant: text('identifiant').notNull(), nom: text('nom').notNull(), @@ -33,8 +33,8 @@ export const actionDefinitionTable = pgTable('action_definition', { contexte: text('contexte').notNull(), exemples: text('exemples').notNull(), ressources: text('ressources').notNull(), - reduction_potentiel: text('reduction_potentiel').notNull(), - perimetre_evaluation: text('perimetre_evaluation').notNull(), + reductionPotentiel: text('reduction_potentiel').notNull(), + perimetreEvaluation: text('perimetre_evaluation').notNull(), preuve: text('preuve'), points: doublePrecision('points'), pourcentage: doublePrecision('pourcentage'), @@ -57,8 +57,8 @@ export const createActionDefinitionSchema = createInsertSchema( export type ActionDefinitionAvecParentType = Pick< ActionDefinitionType, - 'action_id' + 'actionId' > & Partial & { - parent_action_id: string | null; - }; + parentActionId: string | null; +}; diff --git a/backend/src/referentiel/models/action-relation.table.ts b/backend/src/referentiel/models/action-relation.table.ts new file mode 100644 index 0000000000..55af19e12b --- /dev/null +++ b/backend/src/referentiel/models/action-relation.table.ts @@ -0,0 +1,27 @@ +import { InferInsertModel, InferSelectModel } from 'drizzle-orm'; +import { pgTable, varchar } from 'drizzle-orm/pg-core'; +import { createInsertSchema, createSelectSchema } from 'drizzle-zod'; +import { + actionDefinitionTable, + referentielEnum, +} from './action-definition.table'; + +export const actionRelationTable = pgTable('action_relation', { + id: varchar('id', { length: 30 }) + .references(() => actionDefinitionTable.actionId) + .primaryKey() + .notNull(), + referentiel: referentielEnum('referentiel').notNull(), + parent: varchar('parent', { length: 30 }).references( + () => actionDefinitionTable.actionId, + ), +}); + +export type ActionRelationType = InferSelectModel; +export type CreateActionRelationType = InferInsertModel< + typeof actionRelationTable +>; + +export const actionRelationSchema = createSelectSchema(actionRelationTable); +export const createActionRelationSchema = + createInsertSchema(actionRelationTable); From ced69e9979bc0ffa5bb76425ee552df3fe0cedbe Mon Sep 17 00:00:00 2001 From: Amandine Date: Thu, 12 Sep 2024 18:28:40 +0200 Subject: [PATCH 09/22] =?UTF-8?q?Backend=20-=20Ajoute=20la=20r=C3=A9cup?= =?UTF-8?q?=C3=A9ration=20des=20d=C3=A9finitions=20des=20indicateurs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controllers/indicateurs.controller.ts | 14 +- .../models/deleteIndicateurs.models.ts | 8 +- .../models/getIndicateurs.models.ts | 14 +- .../models/indicateur-definition.table.ts | 62 + .../indicateur-source-metadonnee.table.ts | 32 + .../models/indicateur-source.table.ts | 14 + .../models/indicateur-valeur.table.ts | 156 +++ .../indicateurs/models/indicateur.models.ts | 243 ---- .../models/upsertIndicateurs.models.ts | 2 +- .../services/indicateurSources.service.ts | 12 +- .../services/indicateurs.service.spec.ts | 1125 ++++++++--------- .../services/indicateurs.service.ts | 268 ++-- .../test/indicateurs/indicateurs.e2e-spec.ts | 18 +- 13 files changed, 1003 insertions(+), 965 deletions(-) create mode 100644 backend/src/indicateurs/models/indicateur-definition.table.ts create mode 100644 backend/src/indicateurs/models/indicateur-source-metadonnee.table.ts create mode 100644 backend/src/indicateurs/models/indicateur-source.table.ts create mode 100644 backend/src/indicateurs/models/indicateur-valeur.table.ts delete mode 100644 backend/src/indicateurs/models/indicateur.models.ts diff --git a/backend/src/indicateurs/controllers/indicateurs.controller.ts b/backend/src/indicateurs/controllers/indicateurs.controller.ts index 7847c5567b..c64b3ce847 100644 --- a/backend/src/indicateurs/controllers/indicateurs.controller.ts +++ b/backend/src/indicateurs/controllers/indicateurs.controller.ts @@ -2,7 +2,6 @@ import { createZodDto } from '@anatine/zod-nestjs'; import { Body, Controller, Get, Logger, Post, Query } from '@nestjs/common'; import { ApiCreatedResponse, ApiResponse, ApiTags } from '@nestjs/swagger'; import { TokenInfo } from '../../auth/decorators/token-info.decorators'; -import type { SupabaseJwtPayload } from '../../auth/models/auth.models'; import { getIndicateursValeursRequestSchema, getIndicateursValeursResponseSchema, @@ -12,16 +11,17 @@ import { UpsertIndicateursValeursResponse, } from '../models/upsertIndicateurs.models'; import IndicateursService from '../services/indicateurs.service'; +import type { SupabaseJwtPayload } from '../../auth/models/supabase-jwt.models'; /** * 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 */ class GetIndicateursValeursRequestClass extends createZodDto( - getIndicateursValeursRequestSchema + getIndicateursValeursRequestSchema, ) {} class GetIndicateursValeursResponseClass extends createZodDto( - getIndicateursValeursResponseSchema + getIndicateursValeursResponseSchema, ) {} @ApiTags('Indicateurs') @@ -35,11 +35,11 @@ export class IndicateursController { @ApiResponse({ type: GetIndicateursValeursResponseClass }) async getIndicateurValeurs( @Query() request: GetIndicateursValeursRequestClass, - @TokenInfo() tokenInfo: SupabaseJwtPayload + @TokenInfo() tokenInfo: SupabaseJwtPayload, ): Promise { return this.indicateurService.getIndicateurValeursGroupees( request, - tokenInfo + tokenInfo, ); } @@ -49,12 +49,12 @@ export class IndicateursController { }) async upsertIndicateurValeurs( @Body() request: UpsertIndicateursValeursRequest, - @TokenInfo() tokenInfo: SupabaseJwtPayload + @TokenInfo() tokenInfo: SupabaseJwtPayload, ): Promise { const upsertedValeurs = await this.indicateurService.upsertIndicateurValeurs( request.valeurs, - tokenInfo + tokenInfo, ); return { valeurs: upsertedValeurs }; } diff --git a/backend/src/indicateurs/models/deleteIndicateurs.models.ts b/backend/src/indicateurs/models/deleteIndicateurs.models.ts index 03a45c9cc7..fa296e0fc4 100644 --- a/backend/src/indicateurs/models/deleteIndicateurs.models.ts +++ b/backend/src/indicateurs/models/deleteIndicateurs.models.ts @@ -4,13 +4,13 @@ import { z } from 'zod'; export const deleteIndicateursValeursRequestSchema = extendApi( z .object({ - collectivite_id: z.coerce.number().int().openapi({ + collectiviteId: z.coerce.number().int().openapi({ description: 'Identifiant de la collectivité', }), - indicateur_id: z.coerce.number().int().optional().openapi({ + indicateurId: z.coerce.number().int().optional().openapi({ description: "Identifiant de l'indicateur", }), - metadonnee_id: z.coerce.number().int().optional().openapi({ + metadonneeId: z.coerce.number().int().optional().openapi({ description: 'Identifiant de la métadonnée permettant de sélectionner une source', }), @@ -26,7 +26,7 @@ export type DeleteIndicateursValeursRequestType = z.infer< export const deleteIndicateursValeursResponseSchema = extendApi( z .object({ - indicateur_valeur_ids_supprimes: z.array(z.number().int()), + indicateurValeurIdsSupprimes: z.array(z.number().int()), }) .openapi({ title: 'Identifiant des valeurs supprimées', diff --git a/backend/src/indicateurs/models/getIndicateurs.models.ts b/backend/src/indicateurs/models/getIndicateurs.models.ts index 1ab5316f91..f1beb9d48c 100644 --- a/backend/src/indicateurs/models/getIndicateurs.models.ts +++ b/backend/src/indicateurs/models/getIndicateurs.models.ts @@ -1,18 +1,18 @@ import { extendApi } from '@anatine/zod-openapi'; import { z } from 'zod'; -import { indicateurAvecValeursParSourceSchema } from './indicateur.models'; +import { indicateurAvecValeursParSourceSchema } from './indicateur-valeur.table'; export const getIndicateursValeursRequestSchema = extendApi( z .object({ - collectivite_id: z.coerce.number().int().openapi({ + collectiviteId: z.coerce.number().int().openapi({ description: 'Identifiant de la collectivité', }), - indicateur_id: z.coerce.number().int().optional().openapi({ + indicateurId: z.coerce.number().int().optional().openapi({ description: "Identifiant de l'indicateur", }), - identifiants_referentiel: z + identifiantsReferentiel: z .string() .transform((value) => value.split(',')) .pipe(z.string().array()) @@ -29,13 +29,13 @@ export const getIndicateursValeursRequestSchema = extendApi( description: 'Liste des sources (séparées par des virgules). collectivite pour les valeurs renseignées par la collectivité', }), - date_debut: z.string().length(10).optional().openapi({ + dateDebut: z.string().length(10).optional().openapi({ description: 'Date de début (format YYYY-MM-DD)', }), - date_fin: z.string().length(10).optional().openapi({ + dateFin: z.string().length(10).optional().openapi({ description: 'Date de fin (format YYYY-MM-DD)', }), // z.string().date() only supported in 3.23 - ignore_dedoublonnage: z + ignoreDedoublonnage: z .enum(['true', 'false']) .transform((value) => value === 'true') .optional() diff --git a/backend/src/indicateurs/models/indicateur-definition.table.ts b/backend/src/indicateurs/models/indicateur-definition.table.ts new file mode 100644 index 0000000000..28c3bb2852 --- /dev/null +++ b/backend/src/indicateurs/models/indicateur-definition.table.ts @@ -0,0 +1,62 @@ +import { boolean, doublePrecision, integer, pgTable, serial, text, timestamp, uuid } from 'drizzle-orm/pg-core'; +import { collectiviteTable } from '../../collectivites/models/collectivite.table'; +import { InferInsertModel, InferSelectModel, sql } from 'drizzle-orm'; +import { createInsertSchema, createSelectSchema } from 'drizzle-zod'; +import { z } from 'zod'; + +export const indicateurDefinitionTable = pgTable('indicateur_definition', { + id: serial('id').primaryKey(), + groupementId: integer('groupement_id'), // TODO: references + collectiviteId: integer('collectivite_id').references( + () => collectiviteTable.id, + { + onDelete: 'cascade', + }, + ), + identifiantReferentiel: text('identifiant_referentiel').unique(), + titre: text('titre').notNull(), + titreLong: text('titre_long'), + description: text('description'), + unite: text('unite').notNull(), + borneMin: doublePrecision('borne_min'), + borneMax: doublePrecision('borne_max'), + participationScore: boolean('participation_score').default(false).notNull(), + sansValeurUtilisateur: boolean('sans_valeur_utilisateur') + .default(false) + .notNull(), + valeurCalcule: text('valeur_calcule'), + modifiedAt: timestamp('modified_at', { withTimezone: true }) + .default(sql.raw(`CURRENT_TIMESTAMP`)) + .notNull(), // with time zone default CURRENT_TIMESTAMP + createdAt: timestamp('created_at', { withTimezone: true }) + .default(sql.raw(`CURRENT_TIMESTAMP`)) + .notNull(), // with time zone default CURRENT_TIMESTAMP + modifiedBy: uuid('modified_by'), // TODO: default auth.uid() references auth.users + createdBy: uuid('created_by'), // TODO: default auth.uid() references auth.users +}); +export type IndicateurDefinitionType = InferSelectModel< + typeof indicateurDefinitionTable +>; +export type CreateIndicateurDefinitionType = InferInsertModel< + typeof indicateurDefinitionTable +>; +export const indicateurDefinitionSchema = createSelectSchema( + indicateurDefinitionTable, +); +export const createIndicateurDefinitionSchema = createInsertSchema( + indicateurDefinitionTable, +); +export const minimaleIndicateurDefinitionSchema = + indicateurDefinitionSchema.pick({ + id: true, + identifiantReferentiel: true, + titre: true, + titreLong: true, + description: true, + unite: true, + borneMin: true, + borneMax: true, + }); +export type MinimalIndicateurDefinitionType = z.infer< + typeof minimaleIndicateurDefinitionSchema +>; diff --git a/backend/src/indicateurs/models/indicateur-source-metadonnee.table.ts b/backend/src/indicateurs/models/indicateur-source-metadonnee.table.ts new file mode 100644 index 0000000000..92ea6c8300 --- /dev/null +++ b/backend/src/indicateurs/models/indicateur-source-metadonnee.table.ts @@ -0,0 +1,32 @@ +import { pgTable, serial, text, timestamp } from 'drizzle-orm/pg-core'; +import { InferInsertModel, InferSelectModel } from 'drizzle-orm'; +import { createInsertSchema, createSelectSchema } from 'drizzle-zod'; +import { indicateurSourceTable } from './indicateur-source.table'; + +export const indicateurSourceMetadonneeTable = pgTable( + 'indicateur_source_metadonnee', + { + id: serial('id').primaryKey(), + sourceId: text('source_id') + .references(() => indicateurSourceTable.id) + .notNull(), + dateVersion: timestamp('date_version').notNull(), + nomDonnees: text('nom_donnees'), + diffuseur: text('diffuseur'), + producteur: text('producteur'), + methodologie: text('methodologie'), + limites: text('limites'), + }, +); +export type IndicateurSourceMetadonneeType = InferSelectModel< + typeof indicateurSourceMetadonneeTable +>; +export type CreateIndicateurSourceMetadonneeType = InferInsertModel< + typeof indicateurSourceMetadonneeTable +>; +export const indicateurSourceMetadonneeSchema = createSelectSchema( + indicateurSourceMetadonneeTable, +); +export const createIndicateurSourceMetadonneeSchema = createInsertSchema( + indicateurSourceMetadonneeTable, +); diff --git a/backend/src/indicateurs/models/indicateur-source.table.ts b/backend/src/indicateurs/models/indicateur-source.table.ts new file mode 100644 index 0000000000..5821d9180e --- /dev/null +++ b/backend/src/indicateurs/models/indicateur-source.table.ts @@ -0,0 +1,14 @@ +import { integer, pgTable, text } from 'drizzle-orm/pg-core'; +import { InferInsertModel, InferSelectModel } from 'drizzle-orm'; + +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 +>; diff --git a/backend/src/indicateurs/models/indicateur-valeur.table.ts b/backend/src/indicateurs/models/indicateur-valeur.table.ts new file mode 100644 index 0000000000..b0dd58d81b --- /dev/null +++ b/backend/src/indicateurs/models/indicateur-valeur.table.ts @@ -0,0 +1,156 @@ +import { + date, + doublePrecision, + integer, + pgTable, + serial, + text, + timestamp, + uuid, +} from 'drizzle-orm/pg-core'; +import { collectiviteTable } from '../../collectivites/models/collectivite.table'; +import { InferInsertModel, InferSelectModel, sql } from 'drizzle-orm'; +import { createInsertSchema, createSelectSchema } from 'drizzle-zod'; +import { extendApi, extendZodWithOpenApi } from '@anatine/zod-openapi'; +import { z } from 'zod'; +import { createZodDto } from '@anatine/zod-nestjs'; +import { + indicateurDefinitionSchema, + indicateurDefinitionTable, + IndicateurDefinitionType, + minimaleIndicateurDefinitionSchema, +} from './indicateur-definition.table'; +import { + indicateurSourceMetadonneeSchema, + indicateurSourceMetadonneeTable, + IndicateurSourceMetadonneeType, +} from './indicateur-source-metadonnee.table'; +extendZodWithOpenApi(z); + +export const indicateurValeurTable = pgTable('indicateur_valeur', { + id: serial('id').primaryKey(), + collectiviteId: integer('collectivite_id') + .notNull() + .references(() => collectiviteTable.id, { + onDelete: 'cascade', + }), + indicateurId: integer('indicateur_id') + .notNull() + .references(() => indicateurDefinitionTable.id, { + onDelete: 'cascade', + }), + dateValeur: date('date_valeur').notNull(), + metadonneeId: integer('metadonnee_id').references( + () => indicateurSourceMetadonneeTable.id, + { + onDelete: 'cascade', + }, + ), + resultat: doublePrecision('resultat'), + resultatCommentaire: text('resultat_commentaire'), + objectif: doublePrecision('objectif'), + objectifCommentaire: text('objectif_commentaire'), + estimation: doublePrecision('estimation'), + modifiedAt: timestamp('modified_at', { withTimezone: true }) + .default(sql.raw(`CURRENT_TIMESTAMP`)) + .notNull(), // with time zone default CURRENT_TIMESTAMP + createdAt: timestamp('created_at', { withTimezone: true }) + .default(sql.raw(`CURRENT_TIMESTAMP`)) + .notNull(), // with time zone default CURRENT_TIMESTAMP + modifiedBy: uuid('modified_by'), // TODO: default auth.uid() references auth.users + createdBy: uuid('created_by'), // TODO: default auth.uid() references auth.users +}); + +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 IndicateurValeurGroupeeType = z.infer< + typeof indicateurValeurGroupeeSchema +>; + +export class IndicateurValeurGroupee extends createZodDto( + indicateurValeurGroupeeSchema, +) {} + +export const indicateurAvecValeursSchema = extendApi( + z + .object({ + definition: minimaleIndicateurDefinitionSchema, + valeurs: z.array(indicateurValeurGroupeeSchema), + }) + .openapi({ + title: 'Indicateur définition et valeurs ordonnées par date', + }), +); + +export type IndicateurAvecValeursType = z.infer< + typeof indicateurAvecValeursSchema +>; +export class IndicateurAvecValeursClass extends createZodDto( + indicateurAvecValeursSchema, +) {} + +export const indicateurValeursGroupeeParSourceSchema = extendApi( + z + .object({ + source: z.string(), + metadonnees: z.array(indicateurSourceMetadonneeSchema), + valeurs: z.array(indicateurValeurGroupeeSchema), + }) + .openapi({ + title: 'Indicateur valeurs pour une source donnée', + }), +); +export class IndicateurValeursGroupeeParSource extends createZodDto( + indicateurValeursGroupeeParSourceSchema, +) {} + +export const indicateurAvecValeursParSourceSchema = extendApi( + z + .object({ + definition: indicateurDefinitionSchema, + sources: z.record(z.string(), indicateurValeursGroupeeParSourceSchema), + }) + .openapi({ + title: 'Filtre de récupération des valeurs des indicateurs', + }), +); +export class IndicateurAvecValeursParSource extends createZodDto( + indicateurAvecValeursParSourceSchema, +) {} + +export interface IndicateurValeurAvecMetadonnesDefinition { + indicateur_valeur: IndicateurValeurType; + + indicateur_definition: IndicateurDefinitionType | null; + + indicateur_source_metadonnee: IndicateurSourceMetadonneeType | null; +} diff --git a/backend/src/indicateurs/models/indicateur.models.ts b/backend/src/indicateurs/models/indicateur.models.ts deleted file mode 100644 index a99ab43ff1..0000000000 --- a/backend/src/indicateurs/models/indicateur.models.ts +++ /dev/null @@ -1,243 +0,0 @@ -import { createZodDto } from '@anatine/zod-nestjs'; -import { extendApi, extendZodWithOpenApi } from '@anatine/zod-openapi'; -import { InferInsertModel, InferSelectModel, sql } from 'drizzle-orm'; -import { - boolean, - date, - doublePrecision, - integer, - pgTable, - serial, - text, - timestamp, - uuid, -} from 'drizzle-orm/pg-core'; -import { createInsertSchema, createSelectSchema } from 'drizzle-zod'; -import { z } from 'zod'; -import { collectiviteTable } from '../../collectivites/models/collectivite.models'; -extendZodWithOpenApi(z); - -export const indicateurSourceTable = pgTable('indicateur_source', { - id: text('id').primaryKey(), - libelle: text('libelle').notNull(), - ordre_affichage: integer('ordre_affichage'), -}); -export type IndicateurSourceType = InferSelectModel< - typeof indicateurSourceTable ->; -export type CreateIndicateurSourceType = InferInsertModel< - typeof indicateurSourceTable ->; - -export const indicateurSourceMetadonneeTable = pgTable( - 'indicateur_source_metadonnee', - { - id: serial('id').primaryKey(), - source_id: text('source_id') - .references(() => indicateurSourceTable.id) - .notNull(), - date_version: timestamp('date_version').notNull(), - nom_donnees: text('nom_donnees'), - diffuseur: text('diffuseur'), - producteur: text('producteur'), - methodologie: text('methodologie'), - limites: text('limites'), - }, -); -export type IndicateurSourceMetadonneeType = InferSelectModel< - typeof indicateurSourceMetadonneeTable ->; -export type CreateIndicateurSourceMetadonneeType = InferInsertModel< - typeof indicateurSourceMetadonneeTable ->; -export const indicateurSourceMetadonneeSchema = createSelectSchema( - indicateurSourceMetadonneeTable, -); -export const createIndicateurSourceMetadonneeSchema = createInsertSchema( - indicateurSourceMetadonneeTable, -); - -export const indicateurDefinitionTable = pgTable('indicateur_definition', { - id: serial('id').primaryKey(), - groupement_id: integer('groupement_id'), // TODO: references - collectivite_id: integer('collectivite_id').references( - () => collectiviteTable.id, - { - onDelete: 'cascade', - }, - ), - identifiant_referentiel: text('identifiant_referentiel').unique(), - titre: text('titre').notNull(), - titre_long: text('titre_long'), - description: text('description'), - unite: text('unite').notNull(), - borne_min: doublePrecision('borne_min'), - borne_max: doublePrecision('borne_max'), - participation_score: boolean('participation_score').default(false).notNull(), - sans_valeur_utilisateur: boolean('sans_valeur_utilisateur') - .default(false) - .notNull(), - valeur_calcule: text('valeur_calcule'), - modified_at: timestamp('modified_at', { withTimezone: true }) - .default(sql.raw(`CURRENT_TIMESTAMP`)) - .notNull(), // with time zone default CURRENT_TIMESTAMP - created_at: timestamp('created_at', { withTimezone: true }) - .default(sql.raw(`CURRENT_TIMESTAMP`)) - .notNull(), // with time zone default CURRENT_TIMESTAMP - modified_by: uuid('modified_by'), // TODO: default auth.uid() references auth.users - created_by: uuid('created_by'), // TODO: default auth.uid() references auth.users -}); -export type IndicateurDefinitionType = InferSelectModel< - typeof indicateurDefinitionTable ->; -export type CreateIndicateurDefinitionType = InferInsertModel< - typeof indicateurDefinitionTable ->; -export const indicateurDefinitionSchema = createSelectSchema( - indicateurDefinitionTable, -); -export const createIndicateurDefinitionSchema = createInsertSchema( - indicateurDefinitionTable, -); -export const minimaleIndicateurDefinitionSchema = - indicateurDefinitionSchema.pick({ - id: true, - identifiant_referentiel: true, - titre: true, - titre_long: true, - description: true, - unite: true, - borne_min: true, - borne_max: true, - }); -export type MinimalIndicateurDefinitionType = z.infer< - typeof minimaleIndicateurDefinitionSchema ->; - -export const indicateurValeurTable = pgTable('indicateur_valeur', { - id: serial('id').primaryKey(), - collectivite_id: integer('collectivite_id') - .notNull() - .references(() => collectiviteTable.id, { - onDelete: 'cascade', - }), - indicateur_id: integer('indicateur_id') - .notNull() - .references(() => indicateurDefinitionTable.id, { - onDelete: 'cascade', - }), - date_valeur: date('date_valeur').notNull(), - metadonnee_id: integer('metadonnee_id').references( - () => indicateurSourceMetadonneeTable.id, - { - onDelete: 'cascade', - }, - ), - resultat: doublePrecision('resultat'), - resultat_commentaire: text('resultat_commentaire'), - objectif: doublePrecision('objectif'), - objectif_commentaire: text('objectif_commentaire'), - estimation: doublePrecision('estimation'), - modified_at: timestamp('modified_at', { withTimezone: true }) - .default(sql.raw(`CURRENT_TIMESTAMP`)) - .notNull(), // with time zone default CURRENT_TIMESTAMP - created_at: timestamp('created_at', { withTimezone: true }) - .default(sql.raw(`CURRENT_TIMESTAMP`)) - .notNull(), // with time zone default CURRENT_TIMESTAMP - modified_by: uuid('modified_by'), // TODO: default auth.uid() references auth.users - created_by: uuid('created_by'), // TODO: default auth.uid() references auth.users -}); - -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, - date_valeur: true, - resultat: true, - resultat_commentaire: true, - objectif: true, - objectif_commentaire: true, - metadonnee_id: true, - }) - .partial({ - resultat: true, - resultat_commentaire: true, - objectif: true, - objectif_commentaire: true, - metadonnee_id: true, - }), -); - -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), - }) - .openapi({ - title: 'Indicateur définition et valeurs ordonnées par date', - }), -); - -export type IndicateurAvecValeursType = z.infer< - typeof indicateurAvecValeursSchema ->; -export class IndicateurAvecValeursClass extends createZodDto( - indicateurAvecValeursSchema, -) {} - -export const indicateurValeursGroupeeParSourceSchema = extendApi( - z - .object({ - source: z.string(), - metadonnees: z.array(indicateurSourceMetadonneeSchema), - valeurs: z.array(indicateurValeurGroupeeSchema), - }) - .openapi({ - title: 'Indicateur valeurs pour une source donnée', - }), -); -export class IndicateurValeursGroupeeParSource extends createZodDto( - indicateurValeursGroupeeParSourceSchema, -) {} - -export const indicateurAvecValeursParSourceSchema = extendApi( - z - .object({ - definition: indicateurDefinitionSchema, - sources: z.record(z.string(), indicateurValeursGroupeeParSourceSchema), - }) - .openapi({ - title: 'Filtre de récupération des valeurs des indicateurs', - }), -); -export class IndicateurAvecValeursParSource extends createZodDto( - indicateurAvecValeursParSourceSchema, -) {} - -export interface IndicateurValeurAvecMetadonnesDefinition { - indicateur_valeur: IndicateurValeurType; - - indicateur_definition: IndicateurDefinitionType | null; - - indicateur_source_metadonnee: IndicateurSourceMetadonneeType | null; -} diff --git a/backend/src/indicateurs/models/upsertIndicateurs.models.ts b/backend/src/indicateurs/models/upsertIndicateurs.models.ts index ef5215f06d..c5dda6171b 100644 --- a/backend/src/indicateurs/models/upsertIndicateurs.models.ts +++ b/backend/src/indicateurs/models/upsertIndicateurs.models.ts @@ -1,7 +1,7 @@ import { createZodDto } from '@anatine/zod-nestjs'; import { extendApi, extendZodWithOpenApi } from '@anatine/zod-openapi'; import { z } from 'zod'; -import { createIndicateurValeurSchema } from './indicateur.models'; +import { createIndicateurValeurSchema } from './indicateur-valeur.table'; extendZodWithOpenApi(z); export const upsertIndicateursValeursRequestSchema = extendApi( diff --git a/backend/src/indicateurs/services/indicateurSources.service.ts b/backend/src/indicateurs/services/indicateurSources.service.ts index 0c6e68b59b..55602d767a 100644 --- a/backend/src/indicateurs/services/indicateurSources.service.ts +++ b/backend/src/indicateurs/services/indicateurSources.service.ts @@ -3,11 +3,13 @@ import { and, eq } from 'drizzle-orm'; import DatabaseService from '../../common/services/database.service'; import { CreateIndicateurSourceMetadonneeType, - CreateIndicateurSourceType, indicateurSourceMetadonneeTable, IndicateurSourceMetadonneeType, +} from '../models/indicateur-source-metadonnee.table'; +import { + CreateIndicateurSourceType, indicateurSourceTable, -} from '../models/indicateur.models'; +} from '../models/indicateur-source.table'; @Injectable() export default class IndicateurSourcesService { @@ -19,7 +21,7 @@ export default class IndicateurSourcesService { indicateurSourceMetadonneeType: CreateIndicateurSourceMetadonneeType, ) { this.logger.log( - `Création de la metadonnees pour la source d'indicateur ${indicateurSourceMetadonneeType.source_id} et la date ${indicateurSourceMetadonneeType.date_version.toISOString()}`, + `Création de la metadonnees pour la source d'indicateur ${indicateurSourceMetadonneeType.sourceId} et la date ${indicateurSourceMetadonneeType.dateVersion.toISOString()}`, ); const request = this.databaseService.db .insert(indicateurSourceMetadonneeTable) @@ -42,8 +44,8 @@ export default class IndicateurSourcesService { .from(indicateurSourceMetadonneeTable) .where( and( - eq(indicateurSourceMetadonneeTable.source_id, sourceId), - eq(indicateurSourceMetadonneeTable.date_version, dateVersion), + eq(indicateurSourceMetadonneeTable.sourceId, sourceId), + eq(indicateurSourceMetadonneeTable.dateVersion, dateVersion), ), ) .limit(1); diff --git a/backend/src/indicateurs/services/indicateurs.service.spec.ts b/backend/src/indicateurs/services/indicateurs.service.spec.ts index 82f2192c63..0c0c31ab4a 100644 --- a/backend/src/indicateurs/services/indicateurs.service.spec.ts +++ b/backend/src/indicateurs/services/indicateurs.service.spec.ts @@ -3,15 +3,15 @@ import * as _ from 'lodash'; import { DateTime } from 'luxon'; import { AuthService } from '../../auth/services/auth.service'; import DatabaseService from '../../common/services/database.service'; +import IndicateursService from './indicateurs.service'; +import { IndicateurDefinitionType } from '../models/indicateur-definition.table'; import { IndicateurAvecValeursParSource, IndicateurAvecValeursType, - IndicateurDefinitionType, - IndicateurSourceMetadonneeType, IndicateurValeurAvecMetadonnesDefinition, IndicateurValeurType, -} from '../models/indicateur.models'; -import IndicateursService from './indicateurs.service'; +} from '../models/indicateur-valeur.table'; +import { IndicateurSourceMetadonneeType } from '../models/indicateur-source-metadonnee.table'; describe('IndicateursService', () => { let indicateurService: IndicateursService; @@ -34,61 +34,61 @@ describe('IndicateursService', () => { it('Groupe les valeurs par indicateur, trie par date croissante les valeurs', async () => { const indicateur1: IndicateurDefinitionType = { id: 456, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.c', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: 'Emissions de gaz à effet de serre du secteur résidentiel', + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), + modifiedBy: null, + createdBy: null, }; const indicateur2: IndicateurDefinitionType = { id: 457, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.d', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.d', titre: 'Emissions de gaz à effet de serre - tertiaire', - titre_long: 'Emissions de gaz à effet de serre du secteur tertiaire', + titreLong: 'Emissions de gaz à effet de serre du secteur tertiaire', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), + modifiedBy: null, + createdBy: null, }; const indicateur3: IndicateurDefinitionType = { id: 458, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.e', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.e', titre: 'Emissions de gaz à effet de serre - transport routier', - titre_long: + titreLong: 'Emissions de gaz à effet de serre du secteur du transport routier', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), + modifiedBy: null, + createdBy: null, }; const indicateurDefinitions: IndicateurDefinitionType[] = [ indicateur1, @@ -100,51 +100,51 @@ describe('IndicateursService', () => { const indicateurValeurs: IndicateurValeurType[] = [ { id: 10264, - collectivite_id: 4936, - indicateur_id: 456, - date_valeur: '2016-01-01', - metadonnee_id: 1, + collectiviteId: 4936, + indicateurId: 456, + dateValeur: '2016-01-01', + metadonneeId: 1, resultat: null, - resultat_commentaire: null, + resultatCommentaire: null, objectif: 527.25, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, { id: 10263, - collectivite_id: 4936, - indicateur_id: 456, - date_valeur: '2015-01-01', - metadonnee_id: 1, + collectiviteId: 4936, + indicateurId: 456, + dateValeur: '2015-01-01', + metadonneeId: 1, resultat: null, - resultat_commentaire: null, + resultatCommentaire: null, objectif: 513.79, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, { id: 10300, - collectivite_id: 4936, - indicateur_id: 457, - date_valeur: '2016-01-01', - metadonnee_id: 1, + collectiviteId: 4936, + indicateurId: 457, + dateValeur: '2016-01-01', + metadonneeId: 1, resultat: null, - resultat_commentaire: null, + resultatCommentaire: null, objectif: 423.08, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, ]; const indicateurValeursGroupees = @@ -156,23 +156,23 @@ describe('IndicateursService', () => { { definition: { id: 456, - identifiant_referentiel: 'cae_1.c', + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', id: 10263, objectif: 513.79, }, { - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', id: 10264, objectif: 527.25, }, @@ -181,18 +181,17 @@ describe('IndicateursService', () => { { definition: { id: 457, - identifiant_referentiel: 'cae_1.d', + identifiantReferentiel: 'cae_1.d', titre: 'Emissions de gaz à effet de serre - tertiaire', - titre_long: - 'Emissions de gaz à effet de serre du secteur tertiaire', + titreLong: 'Emissions de gaz à effet de serre du secteur tertiaire', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', id: 10300, objectif: 423.08, }, @@ -210,61 +209,61 @@ describe('IndicateursService', () => { it('Groupe les valeurs par indicateur et par source, trie par date croissante les valeurs', async () => { const indicateur1: IndicateurDefinitionType = { id: 456, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.c', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: 'Emissions de gaz à effet de serre du secteur résidentiel', + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), + modifiedBy: null, + createdBy: null, }; const indicateur2: IndicateurDefinitionType = { id: 457, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.d', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.d', titre: 'Emissions de gaz à effet de serre - tertiaire', - titre_long: 'Emissions de gaz à effet de serre du secteur tertiaire', + titreLong: 'Emissions de gaz à effet de serre du secteur tertiaire', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), + modifiedBy: null, + createdBy: null, }; const indicateur3: IndicateurDefinitionType = { id: 458, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.e', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.e', titre: 'Emissions de gaz à effet de serre - transport routier', - titre_long: + titreLong: 'Emissions de gaz à effet de serre du secteur du transport routier', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-12T12:07:14.638Z').toJSDate(), + modifiedBy: null, + createdBy: null, }; const indicateurDefinitions: IndicateurDefinitionType[] = [ indicateur1, @@ -276,9 +275,9 @@ describe('IndicateursService', () => { const indicateurMetadonnees: IndicateurSourceMetadonneeType[] = [ { id: 1, - source_id: 'rare', - date_version: DateTime.fromISO('2024-07-18T00:00:00.000Z').toJSDate(), - nom_donnees: '', + sourceId: 'rare', + dateVersion: DateTime.fromISO('2024-07-18T00:00:00.000Z').toJSDate(), + nomDonnees: '', diffuseur: 'OREC', producteur: '', methodologie: 'Scope 1&2 (approche cadastrale)', @@ -286,9 +285,9 @@ describe('IndicateursService', () => { }, { id: 2, - source_id: 'snbc', - date_version: DateTime.fromISO('2024-07-11T00:00:00.000Z').toJSDate(), - nom_donnees: null, + sourceId: 'snbc', + dateVersion: DateTime.fromISO('2024-07-11T00:00:00.000Z').toJSDate(), + nomDonnees: null, diffuseur: null, producteur: null, methodologie: null, @@ -299,67 +298,67 @@ describe('IndicateursService', () => { const indicateurValeurs: IndicateurValeurType[] = [ { id: 10264, - collectivite_id: 4936, - indicateur_id: 456, - date_valeur: '2016-01-01', - metadonnee_id: 1, + collectiviteId: 4936, + indicateurId: 456, + dateValeur: '2016-01-01', + metadonneeId: 1, resultat: null, - resultat_commentaire: null, + resultatCommentaire: null, objectif: 527.25, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, { id: 10263, - collectivite_id: 4936, - indicateur_id: 456, - date_valeur: '2015-01-01', - metadonnee_id: 1, + collectiviteId: 4936, + indicateurId: 456, + dateValeur: '2015-01-01', + metadonneeId: 1, resultat: null, - resultat_commentaire: null, + resultatCommentaire: null, objectif: 513.79, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, { id: 10264, - collectivite_id: 4936, - indicateur_id: 456, - date_valeur: '2015-01-01', - metadonnee_id: null, + collectiviteId: 4936, + indicateurId: 456, + dateValeur: '2015-01-01', + metadonneeId: null, resultat: 625, - resultat_commentaire: null, + resultatCommentaire: null, objectif: null, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, { id: 10300, - collectivite_id: 4936, - indicateur_id: 457, - date_valeur: '2016-01-01', - metadonnee_id: 3, + collectiviteId: 4936, + indicateurId: 457, + dateValeur: '2016-01-01', + metadonneeId: 3, resultat: null, - resultat_commentaire: null, + resultatCommentaire: null, objectif: 423.08, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-14T14:10:18.891Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, ]; const indicateurValeursGroupees = @@ -373,27 +372,27 @@ describe('IndicateursService', () => { { definition: { id: 456, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.c', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO( + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO( '2024-08-12T12:07:14.638Z', ).toJSDate(), - created_at: DateTime.fromISO( + createdAt: DateTime.fromISO( '2024-08-12T12:07:14.638Z', ).toJSDate(), - modified_by: null, - created_by: null, + modifiedBy: null, + createdBy: null, }, sources: { rare: { @@ -401,11 +400,11 @@ describe('IndicateursService', () => { metadonnees: [ { id: 1, - source_id: 'rare', - date_version: DateTime.fromISO( + sourceId: 'rare', + dateVersion: DateTime.fromISO( '2024-07-18T00:00:00.000Z', ).toJSDate(), - nom_donnees: '', + nomDonnees: '', diffuseur: 'OREC', producteur: '', methodologie: 'Scope 1&2 (approche cadastrale)', @@ -415,15 +414,15 @@ describe('IndicateursService', () => { valeurs: [ { id: 10263, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 513.79, - metadonnee_id: 1, + metadonneeId: 1, }, { id: 10264, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 527.25, - metadonnee_id: 1, + metadonneeId: 1, }, ], }, @@ -431,7 +430,7 @@ describe('IndicateursService', () => { source: 'collectivite', metadonnees: [], valeurs: [ - { id: 10264, date_valeur: '2015-01-01', resultat: 625 }, + { id: 10264, dateValeur: '2015-01-01', resultat: 625 }, ], }, }, @@ -439,27 +438,27 @@ describe('IndicateursService', () => { { definition: { id: 457, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.d', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.d', titre: 'Emissions de gaz à effet de serre - tertiaire', - titre_long: + titreLong: 'Emissions de gaz à effet de serre du secteur tertiaire', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO( + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO( '2024-08-12T12:07:14.638Z', ).toJSDate(), - created_at: DateTime.fromISO( + createdAt: DateTime.fromISO( '2024-08-12T12:07:14.638Z', ).toJSDate(), - modified_by: null, - created_by: null, + modifiedBy: null, + createdBy: null, }, sources: { unknown: { @@ -468,9 +467,9 @@ describe('IndicateursService', () => { valeurs: [ { id: 10300, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 423.08, - metadonnee_id: 3, + metadonneeId: 3, }, ], }, @@ -490,51 +489,47 @@ describe('IndicateursService', () => { { indicateur_valeur: { id: 17, - collectivite_id: 4936, - indicateur_id: 4, - date_valeur: '2015-01-01', - metadonnee_id: 1, + collectiviteId: 4936, + indicateurId: 4, + dateValeur: '2015-01-01', + metadonneeId: 1, resultat: 447868, - resultat_commentaire: null, + resultatCommentaire: null, objectif: null, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:55:09.325Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_definition: { id: 4, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.c', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:54:51.791Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_source_metadonnee: { id: 1, - source_id: 'rare', - date_version: DateTime.fromISO( + sourceId: 'rare', + dateVersion: DateTime.fromISO( '2024-07-18T00:00:00.000Z', ).toJSDate(), - nom_donnees: '', + nomDonnees: '', diffuseur: 'OREC', producteur: '', methodologie: 'Scope 1&2 (approche cadastrale)', @@ -544,51 +539,47 @@ describe('IndicateursService', () => { { indicateur_valeur: { id: 875, - collectivite_id: 4936, - indicateur_id: 4, - date_valeur: '2015-01-01', - metadonnee_id: 2, + collectiviteId: 4936, + indicateurId: 4, + dateValeur: '2015-01-01', + metadonneeId: 2, resultat: null, - resultat_commentaire: null, + resultatCommentaire: null, objectif: 513790, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:57:28.686Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:57:28.686Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:57:28.686Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:57:28.686Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_definition: { id: 4, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.c', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:54:51.791Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_source_metadonnee: { id: 2, - source_id: 'snbc', - date_version: DateTime.fromISO( + sourceId: 'snbc', + dateVersion: DateTime.fromISO( '2024-07-11T00:00:00.000Z', ).toJSDate(), - nom_donnees: null, + nomDonnees: null, diffuseur: null, producteur: null, methodologie: null, @@ -615,51 +606,47 @@ describe('IndicateursService', () => { { indicateur_valeur: { id: 17, - collectivite_id: 4936, - indicateur_id: 4, - date_valeur: '2015-01-01', - metadonnee_id: 1, + collectiviteId: 4936, + indicateurId: 4, + dateValeur: '2015-01-01', + metadonneeId: 1, resultat: 447868, - resultat_commentaire: null, + resultatCommentaire: null, objectif: null, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:55:09.325Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_definition: { id: 4, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.c', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:54:51.791Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_source_metadonnee: { id: 1, - source_id: 'rare', - date_version: DateTime.fromISO( + sourceId: 'rare', + dateVersion: DateTime.fromISO( '2024-07-18T00:00:00.000Z', ).toJSDate(), - nom_donnees: '', + nomDonnees: '', diffuseur: 'OREC', producteur: '', methodologie: 'Scope 1&2 (approche cadastrale)', @@ -669,51 +656,46 @@ describe('IndicateursService', () => { { indicateur_valeur: { id: 18, - collectivite_id: 4936, - indicateur_id: 9, - date_valeur: '2015-01-01', - metadonnee_id: 1, + collectiviteId: 4936, + indicateurId: 9, + dateValeur: '2015-01-01', + metadonneeId: 1, resultat: 471107, - resultat_commentaire: null, + resultatCommentaire: null, objectif: null, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:55:09.325Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_definition: { id: 9, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.d', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.d', titre: 'Emissions de gaz à effet de serre - tertiaire', - titre_long: - 'Emissions de gaz à effet de serre du secteur tertiaire', + titreLong: 'Emissions de gaz à effet de serre du secteur tertiaire', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:54:51.791Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_source_metadonnee: { id: 1, - source_id: 'rare', - date_version: DateTime.fromISO( + sourceId: 'rare', + dateVersion: DateTime.fromISO( '2024-07-18T00:00:00.000Z', ).toJSDate(), - nom_donnees: '', + nomDonnees: '', diffuseur: 'OREC', producteur: '', methodologie: 'Scope 1&2 (approche cadastrale)', @@ -740,51 +722,47 @@ describe('IndicateursService', () => { { indicateur_valeur: { id: 17, - collectivite_id: 4936, - indicateur_id: 4, - date_valeur: '2015-01-01', - metadonnee_id: 1, + collectiviteId: 4936, + indicateurId: 4, + dateValeur: '2015-01-01', + metadonneeId: 1, resultat: 447868, - resultat_commentaire: null, + resultatCommentaire: null, objectif: null, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:55:09.325Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_definition: { id: 4, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.c', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:54:51.791Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_source_metadonnee: { id: 1, - source_id: 'rare', - date_version: DateTime.fromISO( + sourceId: 'rare', + dateVersion: DateTime.fromISO( '2024-07-18T00:00:00.000Z', ).toJSDate(), - nom_donnees: '', + nomDonnees: '', diffuseur: 'OREC', producteur: '', methodologie: 'Scope 1&2 (approche cadastrale)', @@ -794,43 +772,39 @@ describe('IndicateursService', () => { { indicateur_valeur: { id: 875, - collectivite_id: 4936, - indicateur_id: 4, - date_valeur: '2015-01-01', - metadonnee_id: null, + collectiviteId: 4936, + indicateurId: 4, + dateValeur: '2015-01-01', + metadonneeId: null, resultat: null, - resultat_commentaire: null, + resultatCommentaire: null, objectif: 513790, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:57:28.686Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:57:28.686Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:57:28.686Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:57:28.686Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_definition: { id: 4, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.c', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:54:51.791Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_source_metadonnee: null, }, @@ -854,51 +828,47 @@ describe('IndicateursService', () => { { indicateur_valeur: { id: 17, - collectivite_id: 4936, - indicateur_id: 4, - date_valeur: '2015-01-01', - metadonnee_id: 1, + collectiviteId: 4936, + indicateurId: 4, + dateValeur: '2015-01-01', + metadonneeId: 1, resultat: 447868, - resultat_commentaire: null, + resultatCommentaire: null, objectif: null, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:55:09.325Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_definition: { id: 4, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.c', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:54:51.791Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_source_metadonnee: { id: 1, - source_id: 'rare', - date_version: DateTime.fromISO( + sourceId: 'rare', + dateVersion: DateTime.fromISO( '2024-07-18T00:00:00.000Z', ).toJSDate(), - nom_donnees: '', + nomDonnees: '', diffuseur: 'OREC', producteur: '', methodologie: 'Scope 1&2 (approche cadastrale)', @@ -908,51 +878,47 @@ describe('IndicateursService', () => { { indicateur_valeur: { id: 875, - collectivite_id: 2012, - indicateur_id: 4, - date_valeur: '2015-01-01', - metadonnee_id: 1, + collectiviteId: 2012, + indicateurId: 4, + dateValeur: '2015-01-01', + metadonneeId: 1, resultat: null, - resultat_commentaire: null, + resultatCommentaire: null, objectif: 513790, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:57:28.686Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:57:28.686Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:57:28.686Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:57:28.686Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_definition: { id: 4, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.c', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:54:51.791Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_source_metadonnee: { id: 1, - source_id: 'rare', - date_version: DateTime.fromISO( + sourceId: 'rare', + dateVersion: DateTime.fromISO( '2024-07-18T00:00:00.000Z', ).toJSDate(), - nom_donnees: '', + nomDonnees: '', diffuseur: 'OREC', producteur: '', methodologie: 'Scope 1&2 (approche cadastrale)', @@ -979,51 +945,47 @@ describe('IndicateursService', () => { { indicateur_valeur: { id: 17, - collectivite_id: 4936, - indicateur_id: 4, - date_valeur: '2015-01-01', - metadonnee_id: 1, + collectiviteId: 4936, + indicateurId: 4, + dateValeur: '2015-01-01', + metadonneeId: 1, resultat: 447868, - resultat_commentaire: null, + resultatCommentaire: null, objectif: null, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:55:09.325Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_definition: { id: 4, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.c', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:54:51.791Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_source_metadonnee: { id: 1, - source_id: 'rare', - date_version: DateTime.fromISO( + sourceId: 'rare', + dateVersion: DateTime.fromISO( '2024-07-18T00:00:00.000Z', ).toJSDate(), - nom_donnees: '', + nomDonnees: '', diffuseur: 'OREC', producteur: '', methodologie: 'Scope 1&2 (approche cadastrale)', @@ -1033,51 +995,47 @@ describe('IndicateursService', () => { { indicateur_valeur: { id: 875, - collectivite_id: 4936, - indicateur_id: 4, - date_valeur: '2014-01-01', - metadonnee_id: 1, + collectiviteId: 4936, + indicateurId: 4, + dateValeur: '2014-01-01', + metadonneeId: 1, resultat: null, - resultat_commentaire: null, + resultatCommentaire: null, objectif: 513790, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:57:28.686Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:57:28.686Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:57:28.686Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:57:28.686Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_definition: { id: 4, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.c', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO( - '2024-08-27T11:54:51.791Z', - ).toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_source_metadonnee: { id: 1, - source_id: 'rare', - date_version: DateTime.fromISO( + sourceId: 'rare', + dateVersion: DateTime.fromISO( '2024-07-18T00:00:00.000Z', ).toJSDate(), - nom_donnees: '', + nomDonnees: '', diffuseur: 'OREC', producteur: '', methodologie: 'Scope 1&2 (approche cadastrale)', @@ -1103,45 +1061,44 @@ describe('IndicateursService', () => { const indicateurValeur1: IndicateurValeurAvecMetadonnesDefinition = { indicateur_valeur: { id: 17, - collectivite_id: 4936, - indicateur_id: 4, - date_valeur: '2015-01-01', - metadonnee_id: 1, + collectiviteId: 4936, + indicateurId: 4, + dateValeur: '2015-01-01', + metadonneeId: 1, resultat: 447868, - resultat_commentaire: null, + resultatCommentaire: null, objectif: null, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_definition: { id: 4, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.c', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: - 'Emissions de gaz à effet de serre du secteur résidentiel', + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_source_metadonnee: { id: 1, - source_id: 'rare', - date_version: DateTime.fromISO('2024-07-18T00:00:00.000Z').toJSDate(), - nom_donnees: '', + sourceId: 'rare', + dateVersion: DateTime.fromISO('2024-07-18T00:00:00.000Z').toJSDate(), + nomDonnees: '', diffuseur: 'OREC', producteur: '', methodologie: 'Scope 1&2 (approche cadastrale)', @@ -1151,45 +1108,44 @@ describe('IndicateursService', () => { const indicateurValeur2: IndicateurValeurAvecMetadonnesDefinition = { indicateur_valeur: { id: 875, - collectivite_id: 4936, - indicateur_id: 4, - date_valeur: '2015-01-01', - metadonnee_id: 2, + collectiviteId: 4936, + indicateurId: 4, + dateValeur: '2015-01-01', + metadonneeId: 2, resultat: null, - resultat_commentaire: null, + resultatCommentaire: null, objectif: 513790, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-08-27T11:57:28.686Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:57:28.686Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:57:28.686Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:57:28.686Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_definition: { id: 4, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.c', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: - 'Emissions de gaz à effet de serre du secteur résidentiel', + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_source_metadonnee: { id: 2, - source_id: 'rare', - date_version: DateTime.fromISO('2024-08-01T00:00:00.000Z').toJSDate(), - nom_donnees: '', + sourceId: 'rare', + dateVersion: DateTime.fromISO('2024-08-01T00:00:00.000Z').toJSDate(), + nomDonnees: '', diffuseur: 'OREC', producteur: '', methodologie: 'Scope 1&2 (approche cadastrale)', @@ -1226,45 +1182,44 @@ describe('IndicateursService', () => { const indicateurValeur1: IndicateurValeurAvecMetadonnesDefinition = { indicateur_valeur: { id: 17, - collectivite_id: 4936, - indicateur_id: 4, - date_valeur: '2015-01-01', - metadonnee_id: 1, + collectiviteId: 4936, + indicateurId: 4, + dateValeur: '2015-01-01', + metadonneeId: 1, resultat: 447868, - resultat_commentaire: null, + resultatCommentaire: null, objectif: null, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:55:09.325Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_definition: { id: 4, - groupement_id: null, - collectivite_id: null, - identifiant_referentiel: 'cae_1.c', + groupementId: null, + collectiviteId: null, + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: - 'Emissions de gaz à effet de serre du secteur résidentiel', + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, - participation_score: false, - sans_valeur_utilisateur: false, - valeur_calcule: null, - modified_at: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), - created_at: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), - modified_by: null, - created_by: null, + borneMin: null, + borneMax: null, + participationScore: false, + sansValeurUtilisateur: false, + valeurCalcule: null, + modifiedAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + createdAt: DateTime.fromISO('2024-08-27T11:54:51.791Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, indicateur_source_metadonnee: { id: 1, - source_id: 'rare', - date_version: DateTime.fromISO('2024-07-18T00:00:00.000Z').toJSDate(), - nom_donnees: '', + sourceId: 'rare', + dateVersion: DateTime.fromISO('2024-07-18T00:00:00.000Z').toJSDate(), + nomDonnees: '', diffuseur: 'OREC', producteur: '', methodologie: 'Scope 1&2 (approche cadastrale)', diff --git a/backend/src/indicateurs/services/indicateurs.service.ts b/backend/src/indicateurs/services/indicateurs.service.ts index 05ce6e90da..07efd64db6 100644 --- a/backend/src/indicateurs/services/indicateurs.service.ts +++ b/backend/src/indicateurs/services/indicateurs.service.ts @@ -2,6 +2,7 @@ import { Injectable, Logger } from '@nestjs/common'; import { and, eq, + getTableColumns, gte, inArray, isNotNull, @@ -10,15 +11,13 @@ import { or, sql, SQL, - SQLWrapper, + SQLWrapper } from 'drizzle-orm'; import { groupBy, partition } from 'es-toolkit'; import * as _ from 'lodash'; import { NiveauAcces, - SupabaseJwtPayload, - SupabaseRole, -} from '../../auth/models/auth.models'; +} from '../../auth/models/private-utilisateur-droit.table'; import { AuthService } from '../../auth/services/auth.service'; import DatabaseService from '../../common/services/database.service'; import { DeleteIndicateursValeursRequestType } from '../models/deleteIndicateurs.models'; @@ -26,28 +25,35 @@ import { GetIndicateursValeursRequestType, GetIndicateursValeursResponseType, } from '../models/getIndicateurs.models'; +import { groupementTable } from '../../collectivites/models/groupement.table'; +import { groupementCollectiviteTable } from '../../collectivites/models/groupement-collectivite.table'; import { CreateIndicateurValeurType, IndicateurAvecValeursParSource, IndicateurAvecValeursType, - indicateurDefinitionTable, - IndicateurDefinitionType, - indicateurSourceMetadonneeTable, - IndicateurSourceMetadonneeType, IndicateurValeurAvecMetadonnesDefinition, IndicateurValeurGroupee, IndicateurValeursGroupeeParSource, indicateurValeurTable, IndicateurValeurType, +} from '../models/indicateur-valeur.table'; +import { + indicateurDefinitionTable, + IndicateurDefinitionType, MinimalIndicateurDefinitionType, -} from '../models/indicateur.models'; +} from '../models/indicateur-definition.table'; +import { + indicateurSourceMetadonneeTable, + IndicateurSourceMetadonneeType, +} from '../models/indicateur-source-metadonnee.table'; +import { SupabaseJwtPayload, SupabaseRole } from '../../auth/models/supabase-jwt.models'; @Injectable() export default class IndicateursService { private readonly logger = new Logger(IndicateursService.name); /** - * Quand la source_id est NULL, cela signifie que ce sont des donnees saisies par la collectivite + * Quand la sourceId est NULL, cela signifie que ce sont des donnees saisies par la collectivite */ public readonly NULL_SOURCE_ID = 'collectivite'; @@ -62,29 +68,27 @@ export default class IndicateursService { options: GetIndicateursValeursRequestType, ): (SQLWrapper | SQL)[] { const conditions: (SQLWrapper | SQL)[] = [ - eq(indicateurValeurTable.collectivite_id, options.collectivite_id), + eq(indicateurValeurTable.collectiviteId, options.collectiviteId), ]; if ( - options.identifiants_referentiel && - options.identifiants_referentiel.length > 0 + options.identifiantsReferentiel && + options.identifiantsReferentiel.length > 0 ) { conditions.push( inArray( - indicateurDefinitionTable.identifiant_referentiel, - options.identifiants_referentiel, + indicateurDefinitionTable.identifiantReferentiel, + options.identifiantsReferentiel, ), ); } - if (options.date_debut) { - conditions.push( - gte(indicateurValeurTable.date_valeur, options.date_debut), - ); + if (options.dateDebut) { + conditions.push(gte(indicateurValeurTable.dateValeur, options.dateDebut)); } - if (options.date_fin) { - conditions.push(lte(indicateurValeurTable.date_valeur, options.date_fin)); + if (options.dateFin) { + conditions.push(lte(indicateurValeurTable.dateValeur, options.dateFin)); } - if (options.indicateur_id) { - conditions.push(eq(indicateurValeurTable.id, options.indicateur_id)); + if (options.indicateurId) { + conditions.push(eq(indicateurValeurTable.id, options.indicateurId)); } if (options.sources?.length) { const nullSourceId = options.sources.includes(this.NULL_SOURCE_ID); @@ -94,24 +98,80 @@ export default class IndicateursService { ); if (autreSourceIds.length) { const orCondition = or( - isNull(indicateurSourceMetadonneeTable.source_id), - inArray(indicateurSourceMetadonneeTable.source_id, autreSourceIds), + isNull(indicateurSourceMetadonneeTable.sourceId), + inArray(indicateurSourceMetadonneeTable.sourceId, autreSourceIds), ); if (orCondition) { conditions.push(orCondition); } } else { - conditions.push(isNull(indicateurSourceMetadonneeTable.source_id)); + conditions.push(isNull(indicateurSourceMetadonneeTable.sourceId)); } } else { conditions.push( - inArray(indicateurSourceMetadonneeTable.source_id, options.sources), + inArray(indicateurSourceMetadonneeTable.sourceId, options.sources), ); } } return conditions; } + /** + * Récupère les indicateurs prédéfinis et ceux disponibles pour une collectivité + * @param collectiviteId identifiant de la collectivité voulue, vide pour ne récupérer que les indicateurs prédéfinis + * @return les définitions des indicateurs + */ + async getIndicateursDefinitions( + collectiviteId?: number, + ): Promise { + const conditions = []; + const conditionPredefini = and( + isNull(indicateurDefinitionTable.collectiviteId), + isNull(indicateurDefinitionTable.groupementId), + ); + if (collectiviteId) { + conditions.push( + or( + conditionPredefini, + eq(indicateurDefinitionTable.collectiviteId, collectiviteId), + eq(groupementCollectiviteTable.collectiviteId, collectiviteId), + // TODO tester si ça marche comme ça + ), + ); + } else { + conditions.push(conditionPredefini); + } + + return this.databaseService.db + .select(getTableColumns(indicateurDefinitionTable)) + .from(indicateurDefinitionTable) + .leftJoin( + groupementTable, + eq(indicateurDefinitionTable.groupementId, groupementTable.id), + ) + .leftJoin( + groupementCollectiviteTable, + eq(groupementTable.id, groupementCollectiviteTable.groupementId), + ) + .where((and)(...conditions)); + } + + /** + * Récupère les indicateurs predefinis + * @return une map d'indicateurs avec en clé l'identifiant référentiel + */ + async getIndicateursPredefinisMap(): Promise< + Map + > { + const result = await this.getIndicateursDefinitions(); + const toReturn = new Map(); + for (let i = 0; i < result.length; i++) { + const indicateur = result[i]; + toReturn.set(indicateur.identifiantReferentiel!, indicateur); + } + return toReturn; + } + /** * Récupère les valeurs d'indicateurs selon les options données * @param options @@ -128,19 +188,19 @@ export default class IndicateursService { .from(indicateurValeurTable) .leftJoin( indicateurDefinitionTable, - eq(indicateurValeurTable.indicateur_id, indicateurDefinitionTable.id), + eq(indicateurValeurTable.indicateurId, indicateurDefinitionTable.id), ) .leftJoin( indicateurSourceMetadonneeTable, eq( - indicateurValeurTable.metadonnee_id, + indicateurValeurTable.metadonneeId, indicateurSourceMetadonneeTable.id, ), ) .where(and(...conditions)); this.logger.log(`Récupération de ${result.length} valeurs d'indicateurs`); - if (!options.ignore_dedoublonnage) { + if (!options.ignoreDedoublonnage) { // Gère le cas où plusieurs fois la même source avec des métadonnées différentes > on garde les données de la métadonnée la plus récente result = this.dedoublonnageIndicateurValeursParSource(result); @@ -158,16 +218,16 @@ export default class IndicateursService { ); const conditions: (SQLWrapper | SQL)[] = [ - eq(indicateurValeurTable.collectivite_id, options.collectivite_id), + eq(indicateurValeurTable.collectiviteId, options.collectiviteId), ]; - if (options.indicateur_id) { + if (options.indicateurId) { conditions.push( - eq(indicateurValeurTable.indicateur_id, options.indicateur_id), + eq(indicateurValeurTable.indicateurId, options.indicateurId), ); } - if (options.metadonnee_id) { + if (options.metadonneeId) { conditions.push( - eq(indicateurValeurTable.metadonnee_id, options.metadonnee_id), + eq(indicateurValeurTable.metadonneeId, options.metadonneeId), ); } @@ -181,7 +241,7 @@ export default class IndicateursService { this.logger.log( `${deletedIds.length} valeurs d'indicateurs ont été supprimées`, ); - return { indicateur_valeur_ids_supprimes: deletedIds }; + return { indicateurValeurIdsSupprimes: deletedIds }; } async getIndicateurValeursGroupees( @@ -190,7 +250,7 @@ export default class IndicateursService { ): Promise { await this.authService.verifieAccesAuxCollectivites( tokenInfo, - [options.collectivite_id], + [options.collectiviteId], NiveauAcces.LECTURE, ); @@ -201,7 +261,7 @@ export default class IndicateursService { const initialDefinitionsAcc: { [key: string]: IndicateurDefinitionType } = {}; let uniqueIndicateurDefinitions: IndicateurDefinitionType[]; - if (!options.identifiants_referentiel?.length) { + if (!options.identifiantsReferentiel?.length) { uniqueIndicateurDefinitions = Object.values( indicateurValeurs.reduce((acc, v) => { if (v.indicateur_definition?.id) { @@ -214,12 +274,12 @@ export default class IndicateursService { } else { uniqueIndicateurDefinitions = await this.getReferentielIndicateurDefinitions( - options.identifiants_referentiel, + options.identifiantsReferentiel, ); - options.identifiants_referentiel.forEach((identifiant) => { + options.identifiantsReferentiel.forEach((identifiant) => { if ( !uniqueIndicateurDefinitions.find( - (d) => d.identifiant_referentiel === identifiant, + (d) => d.identifiantReferentiel === identifiant, ) ) { this.logger.warn( @@ -230,16 +290,16 @@ export default class IndicateursService { } uniqueIndicateurDefinitions.sort((a, b) => { - if (!a.identifiant_referentiel && !b.identifiant_referentiel) { + if (!a.identifiantReferentiel && !b.identifiantReferentiel) { return 0; } - if (!a.identifiant_referentiel) { + if (!a.identifiantReferentiel) { return 1; } - if (!b.identifiant_referentiel) { + if (!b.identifiantReferentiel) { return -1; } - return a.identifiant_referentiel.localeCompare(b.identifiant_referentiel); + return a.identifiantReferentiel.localeCompare(b.identifiantReferentiel); }); const initialMetadonneesAcc: { @@ -274,7 +334,7 @@ export default class IndicateursService { .from(indicateurDefinitionTable) .where( inArray( - indicateurDefinitionTable.identifiant_referentiel, + indicateurDefinitionTable.identifiantReferentiel, identifiantsReferentiel, ), ); @@ -288,7 +348,7 @@ export default class IndicateursService { ): Promise { if (tokenInfo) { const collectiviteIds = [ - ...new Set(indicateurValeurs.map((v) => v.collectivite_id)), + ...new Set(indicateurValeurs.map((v) => v.collectiviteId)), ]; await this.authService.verifieAccesAuxCollectivites( tokenInfo, @@ -298,8 +358,8 @@ export default class IndicateursService { if (tokenInfo.role === SupabaseRole.AUTHENTICATED && tokenInfo.sub) { indicateurValeurs.forEach((v) => { - v.created_by = tokenInfo.sub; - v.modified_by = tokenInfo.sub; + v.createdBy = tokenInfo.sub; + v.modifiedBy = tokenInfo.sub; }); } } @@ -309,18 +369,18 @@ export default class IndicateursService { ); // On doit distinguer les valeurs avec et sans métadonnées car la clause d'unicité est différente (onConflictDoUpdate) const [indicateurValeursAvecMetadonnees, indicateurValeursSansMetadonnees] = - partition(indicateurValeurs, (v) => Boolean(v.metadonnee_id)); + partition(indicateurValeurs, (v) => Boolean(v.metadonneeId)); const indicateurValeursResultat: IndicateurValeurType[] = []; if (indicateurValeursAvecMetadonnees.length) { this.logger.log( `Upsert des ${indicateurValeursAvecMetadonnees.length} valeurs avec métadonnées des indicateurs ${[ ...new Set( - indicateurValeursAvecMetadonnees.map((v) => v.indicateur_id), + indicateurValeursAvecMetadonnees.map((v) => v.indicateurId), ), ].join( ',', - )} pour les collectivités ${[...new Set(indicateurValeursAvecMetadonnees.map((v) => v.collectivite_id))].join(',')}`, + )} pour les collectivités ${[...new Set(indicateurValeursAvecMetadonnees.map((v) => v.collectiviteId))].join(',')}`, ); const indicateurValeursAvecMetadonneesResultat = await this.databaseService.db @@ -328,27 +388,27 @@ export default class IndicateursService { .values(indicateurValeursAvecMetadonnees) .onConflictDoUpdate({ target: [ - indicateurValeurTable.indicateur_id, - indicateurValeurTable.collectivite_id, - indicateurValeurTable.date_valeur, - indicateurValeurTable.metadonnee_id, + indicateurValeurTable.indicateurId, + indicateurValeurTable.collectiviteId, + indicateurValeurTable.dateValeur, + indicateurValeurTable.metadonneeId, ], - targetWhere: isNotNull(indicateurValeurTable.metadonnee_id), + targetWhere: isNotNull(indicateurValeurTable.metadonneeId), set: { resultat: sql.raw( `excluded.${indicateurValeurTable.resultat.name}`, ), - resultat_commentaire: sql.raw( - `excluded.${indicateurValeurTable.resultat_commentaire.name}`, + resultatCommentaire: sql.raw( + `excluded.${indicateurValeurTable.resultatCommentaire.name}`, ), objectif: sql.raw( `excluded.${indicateurValeurTable.objectif.name}`, ), - objectif_commentaire: sql.raw( - `excluded.${indicateurValeurTable.objectif_commentaire.name}`, + objectifCommentaire: sql.raw( + `excluded.${indicateurValeurTable.objectifCommentaire.name}`, ), - modified_by: sql.raw( - `excluded.${indicateurValeurTable.modified_by.name}`, + modifiedBy: sql.raw( + `excluded.${indicateurValeurTable.modifiedBy.name}`, ), }, }) @@ -362,11 +422,11 @@ export default class IndicateursService { this.logger.log( `Upsert des ${indicateurValeursSansMetadonnees.length} valeurs sans métadonnées des indicateurs ${[ ...new Set( - indicateurValeursSansMetadonnees.map((v) => v.indicateur_id), + indicateurValeursSansMetadonnees.map((v) => v.indicateurId), ), ].join( ',', - )} pour les collectivités ${[...new Set(indicateurValeursSansMetadonnees.map((v) => v.collectivite_id))].join(',')}`, + )} pour les collectivités ${[...new Set(indicateurValeursSansMetadonnees.map((v) => v.collectiviteId))].join(',')}`, ); const indicateurValeursSansMetadonneesResultat = await this.databaseService.db @@ -374,26 +434,26 @@ export default class IndicateursService { .values(indicateurValeursSansMetadonnees) .onConflictDoUpdate({ target: [ - indicateurValeurTable.indicateur_id, - indicateurValeurTable.collectivite_id, - indicateurValeurTable.date_valeur, + indicateurValeurTable.indicateurId, + indicateurValeurTable.collectiviteId, + indicateurValeurTable.dateValeur, ], - targetWhere: isNull(indicateurValeurTable.metadonnee_id), + targetWhere: isNull(indicateurValeurTable.metadonneeId), set: { resultat: sql.raw( `excluded.${indicateurValeurTable.resultat.name}`, ), - resultat_commentaire: sql.raw( - `excluded.${indicateurValeurTable.resultat_commentaire.name}`, + resultatCommentaire: sql.raw( + `excluded.${indicateurValeurTable.resultatCommentaire.name}`, ), objectif: sql.raw( `excluded.${indicateurValeurTable.objectif.name}`, ), - objectif_commentaire: sql.raw( - `excluded.${indicateurValeurTable.objectif_commentaire.name}`, + objectifCommentaire: sql.raw( + `excluded.${indicateurValeurTable.objectifCommentaire.name}`, ), - modified_by: sql.raw( - `excluded.${indicateurValeurTable.modified_by.name}`, + modifiedBy: sql.raw( + `excluded.${indicateurValeurTable.modifiedBy.name}`, ), }, }) @@ -413,7 +473,7 @@ export default class IndicateursService { } = {}; const uniqueIndicateurValeurs = Object.values( indicateurValeurs.reduce((acc, v) => { - const cleUnicite = `${v.indicateur_valeur.indicateur_id}_${v.indicateur_valeur.collectivite_id}_${v.indicateur_valeur.date_valeur}_${v.indicateur_source_metadonnee?.source_id || this.NULL_SOURCE_ID}`; + const cleUnicite = `${v.indicateur_valeur.indicateurId}_${v.indicateur_valeur.collectiviteId}_${v.indicateur_valeur.dateValeur}_${v.indicateur_source_metadonnee?.sourceId || this.NULL_SOURCE_ID}`; if (!acc[cleUnicite]) { acc[cleUnicite] = v; } else { @@ -421,8 +481,8 @@ export default class IndicateursService { if ( v.indicateur_source_metadonnee && acc[cleUnicite].indicateur_source_metadonnee && - v.indicateur_source_metadonnee.date_version > - acc[cleUnicite].indicateur_source_metadonnee.date_version + v.indicateur_source_metadonnee.dateVersion > + acc[cleUnicite].indicateur_source_metadonnee!.dateVersion ) { acc[cleUnicite] = v; } @@ -448,13 +508,13 @@ export default class IndicateursService { def, [ 'id', - 'identifiant_referentiel', + 'identifiantReferentiel', 'titre', - 'titre_long', + 'titreLong', 'description', 'unite', - 'borne_min', - 'borne_max', + 'borneMin', + 'borneMax', ], ) as MinimalIndicateurDefinitionType; acc[def.id.toString()] = minimaleIndicateurDefinition; @@ -466,20 +526,20 @@ export default class IndicateursService { const indicateurAvecValeurs = uniqueIndicateurDefinitions.map( (indicateurDefinition) => { const valeurs = indicateurValeurs - .filter((v) => v.indicateur_id === indicateurDefinition.id) + .filter((v) => v.indicateurId === indicateurDefinition.id) .map((v) => { const indicateurValeurGroupee: IndicateurValeurGroupee = { id: v.id, - date_valeur: v.date_valeur, + dateValeur: v.dateValeur, resultat: v.resultat, objectif: v.objectif, - metadonnee_id: null, + metadonneeId: null, }; if (!commentairesNonInclus) { - indicateurValeurGroupee.resultat_commentaire = - v.resultat_commentaire; - indicateurValeurGroupee.objectif_commentaire = - v.objectif_commentaire; + indicateurValeurGroupee.resultatCommentaire = + v.resultatCommentaire; + indicateurValeurGroupee.objectifCommentaire = + v.objectifCommentaire; } return _.omitBy( indicateurValeurGroupee, @@ -488,7 +548,7 @@ export default class IndicateursService { }); // Trie les valeurs par date valeurs.sort((a, b) => { - return a.date_valeur.localeCompare(b.date_valeur); + return a.dateValeur.localeCompare(b.dateValeur); }); const indicateurAvecValeurs: IndicateurAvecValeursType = { definition: indicateurDefinition, @@ -520,16 +580,16 @@ export default class IndicateursService { const indicateurAvecValeurs = uniqueIndicateurDefinitions.map( (indicateurDefinition) => { const valeurs = indicateurValeurs - .filter((v) => v.indicateur_id === indicateurDefinition.id) + .filter((v) => v.indicateurId === indicateurDefinition.id) .map((v) => { const indicateurValeurGroupee: IndicateurValeurGroupee = { id: v.id, - date_valeur: v.date_valeur, + dateValeur: v.dateValeur, resultat: v.resultat, - resultat_commentaire: v.resultat_commentaire, + resultatCommentaire: v.resultatCommentaire, objectif: v.objectif, - objectif_commentaire: v.objectif_commentaire, - metadonnee_id: v.metadonnee_id, + objectifCommentaire: v.objectifCommentaire, + metadonneeId: v.metadonneeId, }; return _.omitBy( indicateurValeurGroupee, @@ -542,26 +602,26 @@ export default class IndicateursService { Record > = {}; const valeursParSource = groupBy(valeurs, (valeur) => { - if (!valeur.metadonnee_id) { + if (!valeur.metadonneeId) { return this.NULL_SOURCE_ID; } const metadonnee = indicateurMetadonnees.find( - (m) => m.id === valeur.metadonnee_id, + (m) => m.id === valeur.metadonneeId, ); if (!metadonnee) { this.logger.warn( - `Metadonnée introuvable pour l'identifiant ${valeur.metadonnee_id}`, + `Metadonnée introuvable pour l'identifiant ${valeur.metadonneeId}`, ); return this.UNKOWN_SOURCE_ID; } else { - if (!metadonneesUtilisees[metadonnee.source_id]) { - metadonneesUtilisees[metadonnee.source_id] = {}; + if (!metadonneesUtilisees[metadonnee.sourceId]) { + metadonneesUtilisees[metadonnee.sourceId] = {}; } - if (!metadonneesUtilisees[metadonnee.source_id][metadonnee.id]) { - metadonneesUtilisees[metadonnee.source_id][metadonnee.id] = + if (!metadonneesUtilisees[metadonnee.sourceId][metadonnee.id]) { + metadonneesUtilisees[metadonnee.sourceId][metadonnee.id] = metadonnee; } - return metadonnee.source_id; + return metadonnee.sourceId; } }); const sourceMap: Record = {}; @@ -569,7 +629,7 @@ export default class IndicateursService { // Trie les valeurs par date valeursParSource[sourceId] = valeursParSource[sourceId].sort( (a, b) => { - return a.date_valeur.localeCompare(b.date_valeur); + return a.dateValeur.localeCompare(b.dateValeur); }, ); sourceMap[sourceId] = { diff --git a/backend/test/indicateurs/indicateurs.e2e-spec.ts b/backend/test/indicateurs/indicateurs.e2e-spec.ts index 49147cd721..b3463791bd 100644 --- a/backend/test/indicateurs/indicateurs.e2e-spec.ts +++ b/backend/test/indicateurs/indicateurs.e2e-spec.ts @@ -35,7 +35,7 @@ describe('Route de lecture / ecriture des indicateurs', () => { it(`Lecture sans acces`, () => { return request(app.getHttpServer()) - .get('/indicateurs?collectivite_id=3') + .get('/indicateurs?collectiviteId=3') .set('Authorization', `Bearer ${yoloDodoToken}`) .expect(401) .expect({ @@ -49,17 +49,17 @@ describe('Route de lecture / ecriture des indicateurs', () => { const indicateurValeurPayload: UpsertIndicateursValeursRequest = { valeurs: [ { - collectivite_id: 4936, - indicateur_id: 4, - date_valeur: '2015-01-01', - metadonnee_id: 1, + collectiviteId: 4936, + indicateurId: 4, + dateValeur: '2015-01-01', + metadonneeId: 1, resultat: 447868, }, { - collectivite_id: 3895, - indicateur_id: 4, - date_valeur: '2015-01-01', - metadonnee_id: 1, + collectiviteId: 3895, + indicateurId: 4, + dateValeur: '2015-01-01', + metadonneeId: 1, resultat: 54086, }, ], From 16a880973f838e84ffc8fb722d1dbe5d377dedd1 Mon Sep 17 00:00:00 2001 From: Amandine Date: Thu, 12 Sep 2024 18:29:22 +0200 Subject: [PATCH 10/22] Backend - Ajoute les effets attendus --- backend/src/taxonomie/models/effet-attendu.table.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 backend/src/taxonomie/models/effet-attendu.table.ts diff --git a/backend/src/taxonomie/models/effet-attendu.table.ts b/backend/src/taxonomie/models/effet-attendu.table.ts new file mode 100644 index 0000000000..bced20dbd8 --- /dev/null +++ b/backend/src/taxonomie/models/effet-attendu.table.ts @@ -0,0 +1,7 @@ +import { pgTable, serial, text } from 'drizzle-orm/pg-core'; + +export const effetAttenduTable = pgTable('effet_attendu', { + id: serial('id').primaryKey(), + nom: text('nom').notNull(), + notice: text('notice'), +}); From e0762a888fb9b165effefa390956a5bf75b74586 Mon Sep 17 00:00:00 2001 From: Amandine Date: Thu, 12 Sep 2024 18:30:26 +0200 Subject: [PATCH 11/22] Backend - Ajoute les partenaires du panier --- .../models/panier-partenaire.table.ts | 10 +++++++ .../services/panier-partenaire.service.ts | 30 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 backend/src/taxonomie/models/panier-partenaire.table.ts create mode 100644 backend/src/taxonomie/services/panier-partenaire.service.ts diff --git a/backend/src/taxonomie/models/panier-partenaire.table.ts b/backend/src/taxonomie/models/panier-partenaire.table.ts new file mode 100644 index 0000000000..c490a71853 --- /dev/null +++ b/backend/src/taxonomie/models/panier-partenaire.table.ts @@ -0,0 +1,10 @@ +import { pgTable, serial, text } from 'drizzle-orm/pg-core'; +import { InferSelectModel } from 'drizzle-orm'; + +export const panierPartenaireTable = pgTable('panier_partenaire', { + id: serial('id').primaryKey(), + nom: text('nom').notNull(), +}); +export type PanierPartenaireType = InferSelectModel< + typeof panierPartenaireTable +>; diff --git a/backend/src/taxonomie/services/panier-partenaire.service.ts b/backend/src/taxonomie/services/panier-partenaire.service.ts new file mode 100644 index 0000000000..d9f975ad01 --- /dev/null +++ b/backend/src/taxonomie/services/panier-partenaire.service.ts @@ -0,0 +1,30 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { sql } from 'drizzle-orm'; +import DatabaseService from '../../common/services/database.service'; +import DirectusService from '../../directus/service/directus.service'; +import { panierPartenaireTable } from '../models/panier-partenaire.table'; + +@Injectable() +export default class PanierPartenaireService { + private readonly logger = new Logger(PanierPartenaireService.name); + + constructor( + private readonly databaseService: DatabaseService, + private readonly directusService: DirectusService, + ) {} + + /** + * Met à jour les partenaires depuis directus + */ + async majPartenairePanierFromDirectus() { + const partenaires = await this.directusService.getPartenairesFromDirectus(); + await this.databaseService.db + .insert(panierPartenaireTable) + .values(partenaires) + .onConflictDoUpdate({ + target: panierPartenaireTable.id, + set: { nom: sql.raw(`excluded.name`) }, + }); + Logger.log('Sauvegarde des partenaires réussi'); + } +} From be56868110aa9fb834c2cebbf1fbd81d65054a1a Mon Sep 17 00:00:00 2001 From: Amandine Date: Thu, 12 Sep 2024 18:30:57 +0200 Subject: [PATCH 12/22] =?UTF-8?q?Backend=20-=20Ajoute=20les=20actions=20?= =?UTF-8?q?=C3=A0=20impact?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../action-impact-fiche-action.table.ts | 18 ++ .../controllers/action-impact.controllers.ts | 21 ++ .../models/action-impact-action.table.ts | 26 ++ .../models/action-impact-categorie.table.ts | 10 + .../action-impact-cateorie-fnv.table.ts | 22 ++ .../action-impact-effet-attendu.table.ts | 26 ++ ...tion-impact-fourchette-budgetaire.table.ts | 13 + .../models/action-impact-indicateur.table.ts | 26 ++ .../models/action-impact-partenaire.table.ts | 22 ++ .../action-impact-sous-thematique.table.ts | 27 ++ ...on-impact-temps-de-mise-en-oeuvre.table.ts | 9 + .../models/action-impact-thematique.table.ts | 28 ++ .../panier/models/action-impact-tier.table.ts | 6 + .../src/panier/models/action-impact.table.ts | 94 ++++++ .../models/maj-action-impact-datas.dto.ts | 9 + .../panier/services/action-impact.service.ts | 287 ++++++++++++++++++ 16 files changed, 644 insertions(+) create mode 100644 backend/src/fiches/models/action-impact-fiche-action.table.ts create mode 100644 backend/src/panier/controllers/action-impact.controllers.ts create mode 100644 backend/src/panier/models/action-impact-action.table.ts create mode 100644 backend/src/panier/models/action-impact-categorie.table.ts create mode 100644 backend/src/panier/models/action-impact-cateorie-fnv.table.ts create mode 100644 backend/src/panier/models/action-impact-effet-attendu.table.ts create mode 100644 backend/src/panier/models/action-impact-fourchette-budgetaire.table.ts create mode 100644 backend/src/panier/models/action-impact-indicateur.table.ts create mode 100644 backend/src/panier/models/action-impact-partenaire.table.ts create mode 100644 backend/src/panier/models/action-impact-sous-thematique.table.ts create mode 100644 backend/src/panier/models/action-impact-temps-de-mise-en-oeuvre.table.ts create mode 100644 backend/src/panier/models/action-impact-thematique.table.ts create mode 100644 backend/src/panier/models/action-impact-tier.table.ts create mode 100644 backend/src/panier/models/action-impact.table.ts create mode 100644 backend/src/panier/models/maj-action-impact-datas.dto.ts create mode 100644 backend/src/panier/services/action-impact.service.ts diff --git a/backend/src/fiches/models/action-impact-fiche-action.table.ts b/backend/src/fiches/models/action-impact-fiche-action.table.ts new file mode 100644 index 0000000000..e46672a841 --- /dev/null +++ b/backend/src/fiches/models/action-impact-fiche-action.table.ts @@ -0,0 +1,18 @@ +import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; +import { actionImpactTable } from '../../panier/models/action-impact.table'; +import { ficheActionTable } from './fiche-action.table'; + +export const actionImpactFicheActionTable = pgTable( + 'action_impact_fiche_action', + { + ficheId: integer('fiche_id').references(() => ficheActionTable.id), + actionImpactId: integer('action_impact_id').references( + () => actionImpactTable.id, + ), + }, + (table) => { + return { + pk: primaryKey({ columns: [table.ficheId, table.actionImpactId] }), + }; + }, +); diff --git a/backend/src/panier/controllers/action-impact.controllers.ts b/backend/src/panier/controllers/action-impact.controllers.ts new file mode 100644 index 0000000000..94d4e4e27f --- /dev/null +++ b/backend/src/panier/controllers/action-impact.controllers.ts @@ -0,0 +1,21 @@ +import { Controller, Get, Logger, Query } from '@nestjs/common'; +import ActionImpactService from '../services/action-impact.service'; +import { ActionImpactDetailsClass } from '../models/action-impact.table'; +import { ApiResponse } from '@nestjs/swagger'; + +@Controller('actionImpact') +export class ActionImpactController { + private readonly logger = new Logger(ActionImpactController.name); + + constructor(private readonly indicateurService: ActionImpactService) {} + + @Get('details') + @ApiResponse({ type: ActionImpactDetailsClass }) + async fetchActionImpactDetails( + @Query() request: { actionImpactId: number }, + ): Promise { + return this.indicateurService.getActionImpactDetails( + request.actionImpactId, + ); + } +} diff --git a/backend/src/panier/models/action-impact-action.table.ts b/backend/src/panier/models/action-impact-action.table.ts new file mode 100644 index 0000000000..60de4790bb --- /dev/null +++ b/backend/src/panier/models/action-impact-action.table.ts @@ -0,0 +1,26 @@ +import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; +import { actionRelationTable } from '../../referentiel/models/action-relation.table'; +import { actionImpactTable } from './action-impact.table'; +import { text } from 'drizzle-orm/pg-core'; +import { InferSelectModel } from 'drizzle-orm'; + +export const actionImpactActionTable = pgTable( + 'action_impact_action', + { + actionImpactId: integer('action_impact_id') + .notNull() + .references(() => actionImpactTable.id), + actionId: text('action_id') + .notNull() + .references(() => actionRelationTable.id), + }, + (table) => { + return { + pk: primaryKey({ columns: [table.actionImpactId, table.actionId] }), + }; + }, +); + +export type ActionImpactActionType = InferSelectModel< + typeof actionImpactActionTable +>; diff --git a/backend/src/panier/models/action-impact-categorie.table.ts b/backend/src/panier/models/action-impact-categorie.table.ts new file mode 100644 index 0000000000..ccbd79d403 --- /dev/null +++ b/backend/src/panier/models/action-impact-categorie.table.ts @@ -0,0 +1,10 @@ +import { pgTable, text } from 'drizzle-orm/pg-core'; +import { InferSelectModel } from 'drizzle-orm'; + +export const actionImpactCategorieTable = pgTable('action_impact_categorie', { + id: text('id').primaryKey(), + nom: text('nom').notNull(), +}); +export type ActionImpactCategorieType = InferSelectModel< + typeof actionImpactCategorieTable +>; diff --git a/backend/src/panier/models/action-impact-cateorie-fnv.table.ts b/backend/src/panier/models/action-impact-cateorie-fnv.table.ts new file mode 100644 index 0000000000..38eb64c3ca --- /dev/null +++ b/backend/src/panier/models/action-impact-cateorie-fnv.table.ts @@ -0,0 +1,22 @@ +import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; +import { actionImpactTable } from './action-impact.table'; +import { categorieFNVTable } from '../../taxonomie/models/categorie-fnv.table'; + +export const actionImpactCategorieFNVTable = pgTable( + 'action_impact_categorie_fnv', + { + actionImpactId: integer('action_impact_id') + .notNull() + .references(() => actionImpactTable.id), + categorieFnvId: integer('categorie_fnv_id') + .notNull() + .references(() => categorieFNVTable.id), + }, + (table) => { + return { + pk: primaryKey({ + columns: [table.actionImpactId, table.categorieFnvId], + }), + }; + }, +); diff --git a/backend/src/panier/models/action-impact-effet-attendu.table.ts b/backend/src/panier/models/action-impact-effet-attendu.table.ts new file mode 100644 index 0000000000..51e52527e2 --- /dev/null +++ b/backend/src/panier/models/action-impact-effet-attendu.table.ts @@ -0,0 +1,26 @@ +import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; +import { effetAttenduTable } from '../../taxonomie/models/effet-attendu.table'; +import { actionImpactTable } from './action-impact.table'; +import { InferSelectModel } from 'drizzle-orm'; + +export const actionImpactEffetAttenduTable = pgTable( + 'action_impact_effet_attendu', + { + actionImpactId: integer('action_impact_id') + .notNull() + .references(() => actionImpactTable.id), + effetAttenduId: integer('effet_attendu_id') + .notNull() + .references(() => effetAttenduTable.id), + }, + (table) => { + return { + pk: primaryKey({ + columns: [table.actionImpactId, table.effetAttenduId], + }), + }; + }, +); +export type ActionImpactEffetAttenduType = InferSelectModel< + typeof actionImpactEffetAttenduTable +>; diff --git a/backend/src/panier/models/action-impact-fourchette-budgetaire.table.ts b/backend/src/panier/models/action-impact-fourchette-budgetaire.table.ts new file mode 100644 index 0000000000..f23e30170b --- /dev/null +++ b/backend/src/panier/models/action-impact-fourchette-budgetaire.table.ts @@ -0,0 +1,13 @@ +import { pgTable, serial, text } from 'drizzle-orm/pg-core'; +import { InferSelectModel } from 'drizzle-orm'; + +export const actionImpactFourchetteBudgetaireTable = pgTable( + 'action_impact_fourchette_budgetaire', + { + niveau: serial('niveau').primaryKey(), + nom: text('nom').notNull(), + }, +); +export type ActionImpactFourchetteBudgetaireType = InferSelectModel< + typeof actionImpactFourchetteBudgetaireTable +>; diff --git a/backend/src/panier/models/action-impact-indicateur.table.ts b/backend/src/panier/models/action-impact-indicateur.table.ts new file mode 100644 index 0000000000..7a5bcaea00 --- /dev/null +++ b/backend/src/panier/models/action-impact-indicateur.table.ts @@ -0,0 +1,26 @@ +import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; +import { actionImpactTable } from './action-impact.table'; +import { indicateurDefinitionTable } from '../../indicateurs/models/indicateur-definition.table'; +import { InferSelectModel } from 'drizzle-orm'; + +export const actionImpactIndicateurTable = pgTable( + 'action_impact_indicateur', + { + actionImpactId: integer('action_impact_id') + .notNull() + .references(() => actionImpactTable.id), + indicateurId: integer('indicateur_id') + .notNull() + .references(() => indicateurDefinitionTable.id), + }, + (table) => { + return { + pk: primaryKey({ + columns: [table.actionImpactId, table.indicateurId], + }), + }; + }, +); +export type ActionImpactIndicateurType = InferSelectModel< + typeof actionImpactIndicateurTable +>; diff --git a/backend/src/panier/models/action-impact-partenaire.table.ts b/backend/src/panier/models/action-impact-partenaire.table.ts new file mode 100644 index 0000000000..ad4eb79aef --- /dev/null +++ b/backend/src/panier/models/action-impact-partenaire.table.ts @@ -0,0 +1,22 @@ +import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; +import { panierPartenaireTable } from '../../taxonomie/models/panier-partenaire.table'; +import { actionImpactTable } from './action-impact.table'; + +export const actionImpactPartenaireTable = pgTable( + 'action_impact_partenaire', + { + actionImpactId: integer('action_impact_id') + .notNull() + .references(() => actionImpactTable.id), + partenaireId: integer('partenaire_id') + .notNull() + .references(() => panierPartenaireTable.id), + }, + (table) => { + return { + pk: primaryKey({ + columns: [table.actionImpactId, table.partenaireId], + }), + }; + }, +); diff --git a/backend/src/panier/models/action-impact-sous-thematique.table.ts b/backend/src/panier/models/action-impact-sous-thematique.table.ts new file mode 100644 index 0000000000..932ac55764 --- /dev/null +++ b/backend/src/panier/models/action-impact-sous-thematique.table.ts @@ -0,0 +1,27 @@ +import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; +import { sousThematiqueTable } from '../../taxonomie/models/sous-thematique.table'; +import { actionImpactTable } from './action-impact.table'; +import { InferSelectModel } from 'drizzle-orm'; + +export const actionImpactSousThematiqueTable = pgTable( + 'action_impact_sous_thematique', + { + actionImpactId: integer('action_impact_id') + .notNull() + .references(() => actionImpactTable.id), + sousThematiqueId: integer('sous_thematique_id') + .notNull() + .references(() => sousThematiqueTable.id), + }, + (table) => { + return { + pk: primaryKey({ + columns: [table.actionImpactId, table.sousThematiqueId], + }), + }; + }, +); + +export type ActionImpactSousThematiqueType = InferSelectModel< + typeof actionImpactSousThematiqueTable +>; diff --git a/backend/src/panier/models/action-impact-temps-de-mise-en-oeuvre.table.ts b/backend/src/panier/models/action-impact-temps-de-mise-en-oeuvre.table.ts new file mode 100644 index 0000000000..adb15b40b7 --- /dev/null +++ b/backend/src/panier/models/action-impact-temps-de-mise-en-oeuvre.table.ts @@ -0,0 +1,9 @@ +import { pgTable, serial, text } from 'drizzle-orm/pg-core'; + +export const actionImpactTempsDeMiseEnOeuvreTable = pgTable( + 'action_impact_temps_de_mise_en_oeuvre', + { + niveau: serial('niveau').primaryKey(), + nom: text('nom').notNull(), + }, +); diff --git a/backend/src/panier/models/action-impact-thematique.table.ts b/backend/src/panier/models/action-impact-thematique.table.ts new file mode 100644 index 0000000000..e1649c7229 --- /dev/null +++ b/backend/src/panier/models/action-impact-thematique.table.ts @@ -0,0 +1,28 @@ +import { integer, pgTable, primaryKey } from 'drizzle-orm/pg-core'; +import { thematiqueTable } from '../../taxonomie/models/thematique.table'; +import { actionImpactTable } from './action-impact.table'; +import { InferSelectModel } from 'drizzle-orm'; +import { actionImpactIndicateurTable } from './action-impact-indicateur.table'; + +export const actionImpactThematiqueTable = pgTable( + 'action_impact_thematique', + { + actionImpactId: integer('action_impact_id') + .notNull() + .references(() => actionImpactTable.id), + thematiqueId: integer('thematique_id') + .notNull() + .references(() => thematiqueTable.id), + }, + (table) => { + return { + pk: primaryKey({ + columns: [table.actionImpactId, table.thematiqueId], + }), + }; + }, +); + +export type ActionImpactThematiqueType = InferSelectModel< + typeof actionImpactThematiqueTable +>; diff --git a/backend/src/panier/models/action-impact-tier.table.ts b/backend/src/panier/models/action-impact-tier.table.ts new file mode 100644 index 0000000000..c0804f973a --- /dev/null +++ b/backend/src/panier/models/action-impact-tier.table.ts @@ -0,0 +1,6 @@ +import { pgTable, serial, text } from 'drizzle-orm/pg-core'; + +export const actionImpactTierTable = pgTable('action_impact_tier', { + niveau: serial('niveau').primaryKey(), + nom: text('nom').notNull(), +}); diff --git a/backend/src/panier/models/action-impact.table.ts b/backend/src/panier/models/action-impact.table.ts new file mode 100644 index 0000000000..5d33360afd --- /dev/null +++ b/backend/src/panier/models/action-impact.table.ts @@ -0,0 +1,94 @@ +import { InferSelectModel } from 'drizzle-orm'; +import { + boolean, + integer, + jsonb, + pgTable, + serial, + text, +} from 'drizzle-orm/pg-core'; +import { thematiqueSchema, ThematiqueType } from '../../taxonomie/models/thematique.table'; +import { categorieFNVSchema, CategorieFNVType } from '../../taxonomie/models/categorie-fnv.table'; +import { actionImpactTempsDeMiseEnOeuvreTable } from './action-impact-temps-de-mise-en-oeuvre.table'; +import { actionImpactFourchetteBudgetaireTable } from './action-impact-fourchette-budgetaire.table'; +import { actionImpactTierTable } from './action-impact-tier.table'; +import { createSelectSchema } from 'drizzle-zod'; +import { lienSchema, lienType } from '../../documents/models/document-lien.dto'; +import { z } from 'zod'; +import { createZodDto } from '@anatine/zod-nestjs'; +import { createPlanFromPanierRequestSchema } from './create-plan-from-panier.request'; + +export const actionImpactTable = pgTable('action_impact', { + id: serial('id').primaryKey(), + titre: text('titre').notNull(), + description: text('description').notNull(), + descriptionComplementaire: text('description_complementaire') + .notNull() + .default(''), + nbCollectiviteEnCours: integer('nb_collectivite_en_cours') + .notNull() + .default(1), + nbCollectiviteRealise: integer('nb_collectivite_realise') + .notNull() + .default(1), + actionContinue: boolean('action_continue').notNull().default(false), + tempsDeMiseEnOeuvre: integer('temps_de_mise_en_oeuvre') + .notNull() + .default(1) + .references(() => actionImpactTempsDeMiseEnOeuvreTable.niveau), + fourchetteBudgetaire: integer('fourchette_budgetaire') + .notNull() + .default(1) + .references(() => actionImpactFourchetteBudgetaireTable.niveau), + impactTier: integer('impact_tier') + .notNull() + .default(1) + .references(() => actionImpactTierTable.niveau), + subventionsMobilisables: jsonb('subventions_mobilisables'), + ressourcesExternes: jsonb('ressources_externes'), + rex: jsonb('rex'), +}); +export type ActionImpactType = InferSelectModel; + +export const actionImpactSchema = createSelectSchema(actionImpactTable); + +/* Une action à impact avec les liens jsonb transformés en type lien */ +export type ActionImpactTransformeType = Omit< + ActionImpactType, + 'rex' | 'ressourcesExternes' | 'subventionsMobilisables' +> & { + rex: lienType[]; + ressourcesExternes: lienType[]; + subventionsMobilisables: lienType[]; +}; + +export const actionImpactTransformeSchema = actionImpactSchema + .omit({ rex: true, ressourcesExternes: true, subventionsMobilisables: true }) + .extend({ + rex: z.array(lienSchema), + ressourcesExternes: z.array(lienSchema), + subventionsMobilisables: z.array(lienSchema), + }); + +/* Le resumé d'une action à impact, utilisé pour les cartes */ +export type ActionImpactSnippetType = ActionImpactTransformeType & { + thematiques: ThematiqueType[]; +}; + +export const actionImpactSnippetSchema = actionImpactTransformeSchema.extend({ + thematiques: z.array(thematiqueSchema), +}); + +/* Une action à impact avec des informations complémentaires, utilisé par la modale */ +export type ActionImpactDetailsType = ActionImpactTransformeType & { + thematiques: ThematiqueType[] | null; +} & { categoriesFNV: CategorieFNVType[] | null }; + +export const actionImpactDetailsSchema = actionImpactTransformeSchema.extend({ + thematiques: z.array(thematiqueSchema).nullable(), + categoriesFNV: z.array(categorieFNVSchema).nullable(), +}); + +export class ActionImpactDetailsClass extends createZodDto( + actionImpactDetailsSchema, +) {} diff --git a/backend/src/panier/models/maj-action-impact-datas.dto.ts b/backend/src/panier/models/maj-action-impact-datas.dto.ts new file mode 100644 index 0000000000..9119083ed3 --- /dev/null +++ b/backend/src/panier/models/maj-action-impact-datas.dto.ts @@ -0,0 +1,9 @@ +import { SousThematiqueType } from '../../taxonomie/models/sous-thematique.table'; +import { IndicateurDefinitionType } from '../../indicateurs/models/indicateur-definition.table'; +import { SousThematique } from '../../directus/models/directus.models'; + +export type Datas = { + sousThematiques: Map; + indicateurs: Map; + sousThematiquesDirectus: SousThematique[]; +}; diff --git a/backend/src/panier/services/action-impact.service.ts b/backend/src/panier/services/action-impact.service.ts new file mode 100644 index 0000000000..3197c84673 --- /dev/null +++ b/backend/src/panier/services/action-impact.service.ts @@ -0,0 +1,287 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { + ActionImpactDetailsType, + actionImpactTable, +} from '../models/action-impact.table'; +import { eq, getTableColumns, sql } from 'drizzle-orm'; +import { thematiqueTable } from '../../taxonomie/models/thematique.table'; +import { Datas } from '../models/maj-action-impact-datas.dto'; +import { ActionImpact } from '../../directus/models/directus.models'; +import { actionImpactThematiqueTable } from '../models/action-impact-thematique.table'; +import { actionImpactCategorieFNVTable } from '../models/action-impact-cateorie-fnv.table'; +import { categorieFNVTable } from '../../taxonomie/models/categorie-fnv.table'; +import { actionImpactSousThematiqueTable } from '../models/action-impact-sous-thematique.table'; +import { actionImpactIndicateurTable } from '../models/action-impact-indicateur.table'; +import { actionImpactEffetAttenduTable } from '../models/action-impact-effet-attendu.table'; +import { actionImpactPartenaireTable } from '../models/action-impact-partenaire.table'; +import { actionImpactActionTable } from '../models/action-impact-action.table'; +import DatabaseService from '../../common/services/database.service'; +import { actionImpactBanaticCompetenceTable } from '../models/action-impact-banatic-competence.table'; + +@Injectable() +export default class ActionImpactService { + private readonly logger = new Logger(ActionImpactService.name); + + constructor(private readonly databaseService: DatabaseService) {} + + /** + * Récupère une action à impact plus ses thématiques et ses catégories FNV + * @param actionImpactId identifiant de l'action à récupérer + * @return l'action détaillé + */ + async getActionImpactDetails( + actionImpactId: number, + ): Promise { + this.logger.log( + `Récupération du détail de l'action à impact ${actionImpactId}`, + ); + const actions = await this.databaseService.db + .select({ + ...getTableColumns(actionImpactTable), + thematiques: { + id: thematiqueTable.id, + nom: thematiqueTable.nom, + }, + categoriesFNV: { ...getTableColumns(categorieFNVTable) }, + }) + .from(actionImpactTable) + .leftJoin( + actionImpactThematiqueTable, + eq(actionImpactTable.id, actionImpactThematiqueTable.actionImpactId), + ) + .leftJoin( + thematiqueTable, + eq(actionImpactThematiqueTable.thematiqueId, thematiqueTable.id), + ) + .leftJoin( + actionImpactCategorieFNVTable, + eq(actionImpactTable.id, actionImpactCategorieFNVTable.actionImpactId), + ) + .leftJoin( + categorieFNVTable, + eq(actionImpactCategorieFNVTable.categorieFnvId, categorieFNVTable.id), + ) + .where(eq(actionImpactTable.id, actionImpactId)) + .limit(1); + return actions.length > 0 ? (actions[0] as ActionImpactDetailsType) : null; + } + + /** + * Upsert une action à impact en BDD ainsi que les tables associées + * @param action + * @param datas données provenant de directus et de la BDD utiles à la sauvegarde + */ + async majActionImpactFromDirectus( + action: ActionImpact, + datas: Datas, + ): Promise { + // Upsert action_impact + const actionToSave = { + id: action.id, + titre: action.titre, + description: action.description_courte, + fourchetteBudgetaire: action.fourchette_budgetaire?.niveau, + descriptionComplementaire: action.description_longue || '', + tempsDeMiseEnOeuvre: action.temps_de_mise_en_oeuvre?.niveau, + ressourcesExternes: action.ressources_externes, + rex: action.rex, + subventionsMobilisables: action.subventions_mobilisables, + }; + await this.databaseService.db + .insert(actionImpactTable) + .values(actionToSave) + .onConflictDoUpdate({ + target: actionImpactTable.id, + set: { + titre: sql.raw(`excluded.titre`), + description: sql.raw(`excluded.description`), + fourchetteBudgetaire: sql.raw(`excluded.fourchette_budgetaire`), + descriptionComplementaire: sql.raw( + `excluded.description_complementaire`, + ), + tempsDeMiseEnOeuvre: sql.raw(`excluded.temps_de_mise_en_oeuvre`), + ressourcesExternes: sql.raw(`excluded.ressources_externes`), + rex: sql.raw(`excluded.rex`), + subventionsMobilisables: sql.raw(`excluded.subventions_mobilisables`), + }, + }); + Logger.log( + `Action ${action.id} - Sauvegarde de l''action à impact : réussi`, + ); + // Upsert action_impact_thematique + await this.databaseService.db + .delete(actionImpactThematiqueTable) + .where(eq(actionImpactThematiqueTable.actionImpactId, action.id)); + for (const thematique of action.thematiques) { + const query = await this.databaseService.db + .insert(actionImpactThematiqueTable) + .values({ + actionImpactId: action.id, + thematiqueId: thematique.thematique_id, + }); + if (!query) { + Logger.log( + `Action ${action.id} - Sauvegarde de la thématique ${thematique.thematique_id} : échec`, + ); + } else { + Logger.log( + `Action ${action.id} - Sauvegarde de la thématique ${thematique.thematique_id} : réussi`, + ); + } + } + + // Upsert action_impact_sous-thématique + // /!\ sous_thematiques.sous_thematiqueId ne match pas les id en BDD, il faut faire le lien via le nom + await this.databaseService.db + .delete(actionImpactSousThematiqueTable) + .where(eq(actionImpactSousThematiqueTable.actionImpactId, action.id)); + for (const thematique of action.sous_thematiques) { + // Récupère le nom de la sous thématique dans directus + const thematiqueDirectus = datas.sousThematiquesDirectus.find( + (t) => t.id === thematique.sous_thematique_id, + ); + if (thematiqueDirectus) { + // Fait le lien avec la sous thématique en BDD via le nom + const thematiqueBDD = datas.sousThematiques.get(thematiqueDirectus.nom); + if (thematiqueBDD) { + const query = await this.databaseService.db + .insert(actionImpactSousThematiqueTable) + .values({ + actionImpactId: action.id, + sousThematiqueId: thematiqueBDD.id, + }); + if (!query) { + Logger.log( + `Action ${action.id} - Sauvegarde de la sous thématique ${thematiqueBDD.id} : échec`, + ); + } else { + Logger.log( + `Action ${action.id} - Sauvegarde de la sous thématique ${thematiqueBDD.id} : réussi`, + ); + } + } + } + } + + // Upsert action_impact_indicateur + // /!\ Directus fait le lien vers les identifiants référentiels des indicateurs et non les ids BDD + await this.databaseService.db + .delete(actionImpactIndicateurTable) + .where(eq(actionImpactIndicateurTable.actionImpactId, action.id)); + for (const indicateur of action.indicateurs) { + // Récupère l'indentifiant BDD de l'indicateur à partir de son identifiant référentiel + const indicateurId = datas.indicateurs.get( + indicateur.indicateur_predefini_id!, + )?.id; + if (indicateurId) { + const query = await this.databaseService.db + .insert(actionImpactIndicateurTable) + .values({ + actionImpactId: action.id, + indicateurId: indicateurId, + }); + if (!query) { + Logger.log( + `Action ${action.id} - Sauvegarde de l'indicateur ${indicateur.indicateur_predefini_id} : échec`, + ); + } else { + Logger.log( + `Action ${action.id} - Sauvegarde de l'indicateur ${indicateur.indicateur_predefini_id} : réussi`, + ); + } + } + } + + // Upsert action_impact_effet_attendu + await this.databaseService.db + .delete(actionImpactEffetAttenduTable) + .where(eq(actionImpactEffetAttenduTable.actionImpactId, action.id)); + for (const effet of action.effets_attendus) { + await this.databaseService.db + .insert(actionImpactEffetAttenduTable) + .values({ + actionImpactId: action.id, + effetAttenduId: effet.action_impact_effet_attendu_id, + }); + Logger.log( + `Action ${action.id} - Sauvegarde de l'effet attendu ${effet.action_impact_effet_attendu_id} réussi`, + ); + } + + // Upsert action_impact_partenaire + await this.databaseService.db + .delete(actionImpactPartenaireTable) + .where(eq(actionImpactPartenaireTable.actionImpactId, action.id)); + for (const partenaire of action.partenaires) { + const query = await this.databaseService.db + .insert(actionImpactPartenaireTable) + .values({ + actionImpactId: action.id, + partenaireId: partenaire.action_impact_partenaire_id, + }); + if (!query) { + Logger.log( + `Action ${action.id} - Sauvegarde du partenaire ${partenaire.action_impact_partenaire_id} : échec`, + ); + } else { + Logger.log( + `Action ${action.id} - Sauvegarde du partenaire ${partenaire.action_impact_partenaire_id} : réussi`, + ); + } + } + + // Upsert action_impact_action + await this.databaseService.db + .delete(actionImpactActionTable) + .where(eq(actionImpactActionTable.actionImpactId, action.id)); + for (const actionRef of action.actions_referentiel) { + const query = await this.databaseService.db + .insert(actionImpactActionTable) + .values({ + actionImpactId: action.id, + actionId: actionRef.action_referentiel_id, + }); + if (!query) { + Logger.log( + `Action ${action.id} - Sauvegarde de l'action référentiel ${actionRef.action_referentiel_id} : échec`, + ); + } else { + Logger.log( + `Action ${action.id} - Sauvegarde de l'action référentiel ${actionRef.action_referentiel_id} : réussi`, + ); + } + } + + // Upsert action_impact_banatic_competence + await this.databaseService.db + .delete(actionImpactBanaticCompetenceTable) + .where(eq(actionImpactActionTable.actionImpactId, action.id)); + for (const competence of action.banatic_competences) { + const query = await this.databaseService.db + .insert(actionImpactBanaticCompetenceTable) + .values({ + actionImpactId: action.id, + competenceCode: competence.competence_code, + }); + if (!query) { + Logger.log( + `Action ${action.id} - Sauvegarde de la compétence ${competence.competence_code} : échec`, + ); + } else { + Logger.log( + `Action ${action.id} - Sauvegarde de la compétence ${competence.competence_code} : réussi`, + ); + } + } + + // typologie pas importé + // notes_travail pas importé + // statut pas importé + // elements_budgetaires pas importé + // indicateur_impact_carbone pas importé + // competences_communales pas importé + // independamment_competences pas importé + // banatic_competences_parents pas importé + // indicateur_suivi pas importé + } +} From ec5bc921d8e43f40069a6826ef661b1505fff05c Mon Sep 17 00:00:00 2001 From: Amandine Date: Thu, 12 Sep 2024 18:31:18 +0200 Subject: [PATCH 13/22] Backend - Ajoute les paniers --- .../panier/controllers/panier.controllers.ts | 134 ++++++ .../models/action-impact-panier.table.ts | 20 + .../models/action-impact-statut.table.ts | 38 ++ .../models/action-in-panier-statut.request.ts | 19 + .../panier/models/action-in-panier.request.ts | 20 + .../models/create-plan-from-panier.request.ts | 23 + .../models/get-panier-complet.request.ts | 27 ++ .../models/get-panier-complet.response.ts | 56 +++ backend/src/panier/models/panier.table.ts | 38 ++ backend/src/panier/panier.gateway.ts | 23 + backend/src/panier/services/panier.service.ts | 388 ++++++++++++++++ .../services/plan-from-panier.service.ts | 419 ++++++++++++++++++ 12 files changed, 1205 insertions(+) create mode 100644 backend/src/panier/controllers/panier.controllers.ts create mode 100644 backend/src/panier/models/action-impact-panier.table.ts create mode 100644 backend/src/panier/models/action-impact-statut.table.ts create mode 100644 backend/src/panier/models/action-in-panier-statut.request.ts create mode 100644 backend/src/panier/models/action-in-panier.request.ts create mode 100644 backend/src/panier/models/create-plan-from-panier.request.ts create mode 100644 backend/src/panier/models/get-panier-complet.request.ts create mode 100644 backend/src/panier/models/get-panier-complet.response.ts create mode 100644 backend/src/panier/models/panier.table.ts create mode 100644 backend/src/panier/panier.gateway.ts create mode 100644 backend/src/panier/services/panier.service.ts create mode 100644 backend/src/panier/services/plan-from-panier.service.ts diff --git a/backend/src/panier/controllers/panier.controllers.ts b/backend/src/panier/controllers/panier.controllers.ts new file mode 100644 index 0000000000..cf0e13ceda --- /dev/null +++ b/backend/src/panier/controllers/panier.controllers.ts @@ -0,0 +1,134 @@ +import { + Body, + Controller, + Delete, + Get, + Logger, + Post, + Put, + Query, +} from '@nestjs/common'; +import { ApiResponse, ApiTags } from '@nestjs/swagger'; +import PanierService from '../services/panier.service'; +import { PanierClass } from '../models/panier.table'; +import { CollectiviteRequestType } from '../../collectivites/models/collectivite.request'; +import { ActionInPanierRequestClass } from '../models/action-in-panier.request'; +import { ActionInPanierStatutRequestClass } from '../models/action-in-panier-statut.request'; +import { PanierCompletClass } from '../models/get-panier-complet.response'; +import { GetPanierCompletRequestClass } from '../models/get-panier-complet.request'; +import { CreatePlanFromPanierRequestClass } from '../models/create-plan-from-panier.request'; +import { TokenInfo } from '../../auth/decorators/token-info.decorators'; +import { SupabaseJwtPayload } from '../../auth/models/supabase-jwt.models'; +import PlanFromPanierService from '../services/plan-from-panier.service'; + +@ApiTags('Panier') +@Controller('panier') +export class PanierController { + private readonly logger = new Logger(PanierController.name); + + constructor( + private readonly panierService: PanierService, + private readonly planFromPanierService: PlanFromPanierService, + ) {} + + @Get('') + @ApiResponse({ type: PanierClass }) + async panierFromLanding( + @Query() request: CollectiviteRequestType, + ): Promise { + if (request.collectivite_id) { + this.logger.log( + `Récupération du panier de la collectivité ${request.collectivite_id}.`, + ); + } else { + this.logger.log(`Création d'un nouveau panier.`); + } + return this.panierService.getPanier(request.collectivite_id); + } + + @Post('action_impact') + async addActionToPanier( + @Body() request: ActionInPanierRequestClass, + ): Promise { + this.logger.log( + `Ajoute l'action ${request.actionImpactId} au panier ${request.panierId}`, + ); + await this.panierService.addActionImpact( + request.actionImpactId, + request.panierId, + ); + } + + @Delete('action_impact') + async removeActionFromPanier( + @Query() request: ActionInPanierRequestClass, + ): Promise { + this.logger.log( + `Enlève l'action ${request.actionImpactId} au panier ${request.panierId}`, + ); + await this.panierService.removeActionImpact( + request.actionImpactId, + request.panierId, + ); + } + + @Put('action_impact/statut') + async setActionStatut( + @Body() request: ActionInPanierStatutRequestClass, + ): Promise { + this.logger.log( + `Change le statut de l'action ${request.actionImpactId} dans le panier ${request.panierId} par ${request.categorieId}`, + ); + await this.panierService.setActionImpactCategorie( + request.actionImpactId, + request.panierId, + request.categorieId || null, + ); + } + + @Get('contenu') + @ApiResponse({ type: PanierCompletClass }) + async fetchPanier( + @Query() request: GetPanierCompletRequestClass, + ): Promise { + this.logger.log(`Récupération du contenu du panier ${request.panierId}.`); + return this.panierService.getPanierComplet( + request.panierId, + request.thematiquesIds, + request.niveauxBudget, + request.niveauxTemps, + ); + } + + @Post('contenu') + async createPlanFromPanier( + @Body() request: CreatePlanFromPanierRequestClass, + @TokenInfo() tokenInfo: SupabaseJwtPayload, + ): Promise { + if (request.planId) { + this.logger.log( + `Ajoute le contenu du panier ${request.panierId} au plan ${request.planId} pour la collectivité ${request.collectiviteId}`, + ); + } else { + this.logger.log( + `Cree un plan à partir du panier ${request.panierId} pour la collectivité ${request.collectiviteId}`, + ); + } + return await this.planFromPanierService.addPlanFromPanier( + tokenInfo, + request.collectiviteId, + request.panierId, + request.planId, + ); + } + + @Put('directus') + async majPanierFromDirectus( + @TokenInfo() tokenInfo: SupabaseJwtPayload, + ): Promise { + this.logger.log( + `Met à jour les contenus du panier dans l'app par rapport au contenu dans Directus.`, + ); + await this.panierService.majPanierFromDirectus(tokenInfo); + } +} diff --git a/backend/src/panier/models/action-impact-panier.table.ts b/backend/src/panier/models/action-impact-panier.table.ts new file mode 100644 index 0000000000..36463e7908 --- /dev/null +++ b/backend/src/panier/models/action-impact-panier.table.ts @@ -0,0 +1,20 @@ +import { integer, pgTable, primaryKey, uuid } from 'drizzle-orm/pg-core'; +import { actionImpactTable } from './action-impact.table'; +import { panierTable } from './panier.table'; + +export const actionImpactPanierTable = pgTable( + 'action_impact_panier', + { + panierId: uuid('panier_id') + .notNull() + .references(() => panierTable.id), + actionId: integer('action_id') + .notNull() + .references(() => actionImpactTable.id), + }, + (table) => { + return { + pk: primaryKey({ columns: [table.panierId, table.actionId] }), + }; + }, +); diff --git a/backend/src/panier/models/action-impact-statut.table.ts b/backend/src/panier/models/action-impact-statut.table.ts new file mode 100644 index 0000000000..0d9e5d85db --- /dev/null +++ b/backend/src/panier/models/action-impact-statut.table.ts @@ -0,0 +1,38 @@ +import { + integer, + pgTable, + primaryKey, + text, + uuid, +} from 'drizzle-orm/pg-core'; +import { actionImpactTable } from './action-impact.table'; +import { InferSelectModel } from 'drizzle-orm'; +import { panierTable } from './panier.table'; +import { actionImpactCategorieTable } from './action-impact-categorie.table'; +import { createSelectSchema } from 'drizzle-zod'; + +export const actionImpactStatutTable = pgTable( + 'action_impact_statut', + { + panierId: uuid('panier_id') + .notNull() + .references(() => panierTable.id), + actionId: integer('action_id') + .notNull() + .references(() => actionImpactTable.id), + categorieId: text('categorie_id') + .notNull() + .references(() => actionImpactCategorieTable.id), + }, + (table) => { + return { + pk: primaryKey({ columns: [table.panierId, table.actionId] }), + }; + }, +); +export type ActionImpactStatutType = InferSelectModel< + typeof actionImpactStatutTable +>; +export const actionImpactStatutSchema = createSelectSchema( + actionImpactStatutTable, +); diff --git a/backend/src/panier/models/action-in-panier-statut.request.ts b/backend/src/panier/models/action-in-panier-statut.request.ts new file mode 100644 index 0000000000..8d5f7873d5 --- /dev/null +++ b/backend/src/panier/models/action-in-panier-statut.request.ts @@ -0,0 +1,19 @@ +import { extendApi } from '@anatine/zod-openapi'; +import { createZodDto } from '@anatine/zod-nestjs'; +import { actionInPanierRequestSchema } from './action-in-panier.request'; +import { z } from 'zod'; + +export const ActionInPanierStatutRequestSchema = extendApi( + actionInPanierRequestSchema.extend({ + categorieId: z + .string() + .optional() + .openapi({ description: `Identifiant du statut` }), + }).openapi({ + title: `Statut d'une action à impact dans un panier.`, + }), +); + +export class ActionInPanierStatutRequestClass extends createZodDto( + ActionInPanierStatutRequestSchema, +) {} diff --git a/backend/src/panier/models/action-in-panier.request.ts b/backend/src/panier/models/action-in-panier.request.ts new file mode 100644 index 0000000000..74929ec55b --- /dev/null +++ b/backend/src/panier/models/action-in-panier.request.ts @@ -0,0 +1,20 @@ +import { extendApi } from '@anatine/zod-openapi'; +import { z } from 'zod'; +import { createZodDto } from '@anatine/zod-nestjs'; + +export const actionInPanierRequestSchema = extendApi( + z + .object({ + actionImpactId: z + .number() + .openapi({ description: `Identifiant de l'action à impact` }), + panierId: z.string().openapi({ description: `Identifiant du panier` }), + }) + .openapi({ + title: 'Action à impact dans un panier.', + }), +); + +export class ActionInPanierRequestClass extends createZodDto( + actionInPanierRequestSchema, +) {} diff --git a/backend/src/panier/models/create-plan-from-panier.request.ts b/backend/src/panier/models/create-plan-from-panier.request.ts new file mode 100644 index 0000000000..18c591c7c3 --- /dev/null +++ b/backend/src/panier/models/create-plan-from-panier.request.ts @@ -0,0 +1,23 @@ +import { extendApi } from '@anatine/zod-openapi'; +import { z } from 'zod'; +import { createZodDto } from '@anatine/zod-nestjs'; + +export const createPlanFromPanierRequestSchema = extendApi( + z + .object({ + collectiviteId: z + .number() + .openapi({ description: `Identifiant de la collectivité` }), + panierId: z.string().openapi({ description: `Identifiant du panier` }), + planId: z.number().optional().openapi({ + description: `Identifiant du plan, vide pour créer un nouveau plan`, + }), + }) + .openapi({ + title: 'Panier à transformer en plan pour une collectivité.', + }), +); + +export class CreatePlanFromPanierRequestClass extends createZodDto( + createPlanFromPanierRequestSchema, +) {} \ No newline at end of file diff --git a/backend/src/panier/models/get-panier-complet.request.ts b/backend/src/panier/models/get-panier-complet.request.ts new file mode 100644 index 0000000000..d4ca21ba12 --- /dev/null +++ b/backend/src/panier/models/get-panier-complet.request.ts @@ -0,0 +1,27 @@ +import { extendApi } from '@anatine/zod-openapi'; +import { z } from 'zod'; +import { createZodDto } from '@anatine/zod-nestjs'; + +export const getPanierCompletRequestSchema = extendApi( + z + .object({ + panierId: z.string().openapi({ description: `Identifiant du panier` }), + thematiquesIds: z + .array(z.number()) + .openapi({ description: `Identifiant des thématiques` }), + niveauxBudget: z + .array(z.number()) + .openapi({ description: `Niveaux des budgets` }), + niveauxTemps: z + .array(z.number()) + .openapi({ description: `Niveaux des temps de mise en oeuvre` }), + }) + .openapi({ + title: + 'Identifiant du panier et filtres à appliquer sur le contenu à récupérer.', + }), +); + +export class GetPanierCompletRequestClass extends createZodDto( + getPanierCompletRequestSchema, +) {} \ No newline at end of file diff --git a/backend/src/panier/models/get-panier-complet.response.ts b/backend/src/panier/models/get-panier-complet.response.ts new file mode 100644 index 0000000000..4a1b56fde8 --- /dev/null +++ b/backend/src/panier/models/get-panier-complet.response.ts @@ -0,0 +1,56 @@ +import { + actionImpactSnippetSchema, + ActionImpactSnippetType, + actionImpactTransformeSchema, + ActionImpactTransformeType, +} from './action-impact.table'; +import { + actionImpactStatutSchema, + ActionImpactStatutType, +} from './action-impact-statut.table'; +import { + thematiqueSchema, + ThematiqueType, +} from '../../taxonomie/models/thematique.table'; +import { panierSchema, PanierType } from './panier.table'; +import { createZodDto } from '@anatine/zod-nestjs'; +import { extendApi } from '@anatine/zod-openapi'; +import { z } from 'zod'; + +export type ActionImpactStateType = { + action: ActionImpactTransformeType; + isinpanier: boolean; + statut: ActionImpactStatutType | null; + thematiques: ThematiqueType[]; +}; + +export const actionImpactStateSchema = extendApi( + z.object({ + action: actionImpactTransformeSchema, + isinpanier: z.boolean(), + statut: actionImpactStatutSchema.nullable(), + thematiques: z.array(thematiqueSchema), + }), +); + +export type PanierCompletType = + /* Le panier en tant que tel */ + PanierType & { + /* Liste des actions ajoutée au panier */ + contenu: ActionImpactSnippetType[]; + /* Liste de toutes les actions avec leurs states. */ + states: ActionImpactStateType[]; + }; + +export const panierCompletSchema = extendApi( + panierSchema + .extend({ + contenu: z.array(actionImpactSnippetSchema), + states: z.array(actionImpactStateSchema), + }) + .openapi({ + title: `Panier d'une collectivité avec son contenu.`, + }), +); + +export class PanierCompletClass extends createZodDto(panierCompletSchema) {} diff --git a/backend/src/panier/models/panier.table.ts b/backend/src/panier/models/panier.table.ts new file mode 100644 index 0000000000..1876b47a9d --- /dev/null +++ b/backend/src/panier/models/panier.table.ts @@ -0,0 +1,38 @@ +import { InferSelectModel, SQL, sql } from 'drizzle-orm'; +import { + boolean, + integer, + pgTable, + timestamp, + uuid, +} from 'drizzle-orm/pg-core'; +import { collectiviteTable } from '../../collectivites/models/collectivite.table'; +import { createSelectSchema } from 'drizzle-zod'; +import { createZodDto } from '@anatine/zod-nestjs'; + +export const panierTable = pgTable('panier', { + id: uuid('id').primaryKey().defaultRandom(), + createdAt: timestamp('created_at', { + withTimezone: true, + }) + .notNull() + .defaultNow(), + createdBy: uuid('created_by'), // TODO references auth.users + collectiviteId: integer('collectivite_id').references( + () => collectiviteTable.id, + ), + collectivitePreset: integer('collectivite_preset') + .unique() + .references(() => collectiviteTable.id), + latestUpdate: timestamp('latest_update', { withTimezone: true }) + .notNull() + .defaultNow(), + private: boolean('private').generatedAlwaysAs( + (): SQL => sql`(${panierTable.collectiviteId} is not null)`, + ), +}); +export type PanierType = InferSelectModel; + +export const panierSchema = createSelectSchema(panierTable); + +export class PanierClass extends createZodDto(panierSchema) {} diff --git a/backend/src/panier/panier.gateway.ts b/backend/src/panier/panier.gateway.ts new file mode 100644 index 0000000000..46f8892b60 --- /dev/null +++ b/backend/src/panier/panier.gateway.ts @@ -0,0 +1,23 @@ +import { Logger } from '@nestjs/common'; +import { + OnGatewayInit, + WebSocketGateway, + WebSocketServer, +} from '@nestjs/websockets'; +import { Server } from 'socket.io'; + +@WebSocketGateway() +export class PanierGateway implements OnGatewayInit { + private readonly logger = new Logger(PanierGateway.name); + + @WebSocketServer() server: Server | undefined; + + afterInit() { + this.logger.log('WebSocket server initialized'); + } + + emitPanierUpdate(panierId: any) { + // @ts-ignore + this.server.emit('panierUpdate', panierId); + } +} diff --git a/backend/src/panier/services/panier.service.ts b/backend/src/panier/services/panier.service.ts new file mode 100644 index 0000000000..6a542c987c --- /dev/null +++ b/backend/src/panier/services/panier.service.ts @@ -0,0 +1,388 @@ +import { Injectable, Logger, UnauthorizedException } from '@nestjs/common'; +import { and, eq, gt, inArray, isNotNull, isNull, sql } from 'drizzle-orm'; +import DatabaseService from '../../common/services/database.service'; +import { panierTable, PanierType } from '../models/panier.table'; +import { + ActionImpactSnippetType, + actionImpactTable, +} from '../models/action-impact.table'; +import { thematiqueTable } from '../../taxonomie/models/thematique.table'; +import ActionImpactService from './action-impact.service'; +import { PanierGateway } from '../panier.gateway'; +import AxeService from '../../fiches/services/axe.service'; +import FicheService from '../../fiches/services/fiche.service'; +import DocumentService from '../../documents/services/document.service'; +import PanierPartenaireService from '../../taxonomie/services/panier-partenaire.service'; +import DirectusService from '../../directus/service/directus.service'; +import { Datas } from '../models/maj-action-impact-datas.dto'; +import ThematiqueService from '../../taxonomie/services/thematique.service'; +import IndicateursService from '../../indicateurs/services/indicateurs.service'; +import { actionImpactCategorieTable } from '../models/action-impact-categorie.table'; +import { actionImpactThematiqueTable } from '../models/action-impact-thematique.table'; +import { actionImpactPanierTable } from '../models/action-impact-panier.table'; +import { actionImpactStatutTable } from '../models/action-impact-statut.table'; +import { + ActionImpactStateType, + PanierCompletType, +} from '../models/get-panier-complet.response'; +import { + SupabaseJwtPayload, + SupabaseRole, +} from '../../auth/models/supabase-jwt.models'; + +@Injectable() +export default class PanierService { + private readonly logger = new Logger(PanierService.name); + + constructor( + private readonly databaseService: DatabaseService, + private readonly panierGateway: PanierGateway, + private readonly panierPartenaireService: PanierPartenaireService, + private readonly directusService: DirectusService, + private readonly thematiqueService: ThematiqueService, + private readonly indicateurService: IndicateursService, + private readonly actionImpactService: ActionImpactService, + ) {} + + /** + * Récupère le panier de la collectivité et le créé s'il n'en existe pas un récent (moins d'un mois) + * @param collectiviteId identifiant de la collectivité + * @return le panier de la collectivité + */ + async getPanier(collectiviteId?: number): Promise { + let panier = null; + if (collectiviteId) { + const paniers = await this.databaseService.db + .select() + .from(panierTable) + .where( + and( + eq(panierTable.collectivitePreset, collectiviteId), + isNull(panierTable.collectiviteId), + gt( + panierTable.createdAt, + sql.raw(`current_timestamp - interval '1 month'`), + ), + ), + ); + panier = paniers.length > 0 ? paniers[0] : null; + } + if (!panier) { + const paniers = await this.databaseService.db + .insert(panierTable) + .values({ + collectiviteId: null, + collectivitePreset: collectiviteId ? collectiviteId : null, + }) + .returning(); + panier = paniers.length > 0 ? paniers[0] : null; + } + return panier; + } + + /** + * Ajoute une action à impact à un panier + * @param actionId identifiant de l'action à impact + * @param panierId identifiant du panier + */ + async addActionImpact(actionId: number, panierId: string): Promise { + this.logger.log(`Ajout de l'action ${actionId} dans le panier ${panierId}`); + await this.databaseService.db.insert(actionImpactPanierTable).values({ + actionId: actionId, + panierId: panierId, + }); + this.panierGateway.emitPanierUpdate(panierId); + } + + /** + * Enlève une action à impact à un panier + * @param actionId identifiant de l'action à impact + * @param panierId identifiant du panier + */ + async removeActionImpact(actionId: number, panierId: string): Promise { + this.logger.log(`Retrait de l'action ${actionId} du panier ${panierId}`); + await this.databaseService.db + .delete(actionImpactPanierTable) + .where( + and( + eq(actionImpactPanierTable.actionId, actionId), + eq(actionImpactPanierTable.panierId, panierId), + ), + ); + this.panierGateway.emitPanierUpdate(panierId); + } + + /** + * Modifie le statut d'une action à impact pour un panier donné + * @param actionId identifiant de l'action à impact + * @param panierId identifiant du panier + * @param categorieId identifiant de la catégorie, null pour l'enlever + */ + async setActionImpactCategorie( + actionId: number, + panierId: string, + categorieId: string | null, + ): Promise { + if (categorieId) { + this.logger.log( + `Remplacement par le statut ${categorieId} sur l'action ${actionId} pour le panier ${panierId}`, + ); + await this.databaseService.db + .insert(actionImpactStatutTable) + .values({ + actionId: actionId, + panierId: panierId, + categorieId: categorieId, + }) + .onConflictDoUpdate({ + target: [ + actionImpactStatutTable.actionId, + actionImpactStatutTable.panierId, + ], + set: { categorieId: categorieId }, + }); + } else { + this.logger.log( + `Retrait de la catégorie sur l'action ${actionId} pour le panier ${panierId}`, + ); + await this.databaseService.db + .delete(actionImpactCategorieTable) + .where( + and( + eq(actionImpactPanierTable.actionId, actionId), + eq(actionImpactPanierTable.panierId, panierId), + ), + ); + } + this.panierGateway.emitPanierUpdate(panierId); + } + + /** + * Récupère la liste d'actions à impact avec leur statut vis à vis d'un panier selon des filtres + * @param panierId identifiant d'un panier + * @param thematiqueIds identifiants des thématiques voulus + * @param niveauxBudget identifiants des niveaux de budgets voulus + * @param niveauxTemps identifiants des niveaux de temps voulus + * @return les actions à impact filtrées + */ + async getActionImpactsFiltered( + panierId: string, + thematiqueIds: number[], + niveauxBudget: number[], + niveauxTemps: number[], + ): Promise { + const where = []; + + if (thematiqueIds && thematiqueIds.length > 0) { + where.push(isNotNull(thematiqueTable.id)); // TODO pas sure que ça marche + where.push(inArray(thematiqueTable.id, thematiqueIds)); + } + if (niveauxBudget && niveauxBudget.length > 0) { + where.push(isNotNull(actionImpactTable.fourchetteBudgetaire)); + where.push( + inArray(actionImpactTable.fourchetteBudgetaire, niveauxBudget), + ); + } + if (niveauxTemps && niveauxTemps.length > 0) { + where.push(isNotNull(actionImpactTable.tempsDeMiseEnOeuvre)); + where.push(inArray(actionImpactTable.tempsDeMiseEnOeuvre, niveauxTemps)); + } + + const actions = await this.databaseService.db + .select({ + action: actionImpactTable, + statut: actionImpactStatutTable, + thematique: thematiqueTable, + isInPanier: actionImpactPanierTable.actionId, + }) + .from(actionImpactTable) + .leftJoin( + actionImpactStatutTable, + and( + eq(actionImpactTable.id, actionImpactStatutTable.actionId), + eq(actionImpactStatutTable.panierId, panierId), + ), + ) + .leftJoin( + actionImpactThematiqueTable, + eq(actionImpactTable.id, actionImpactThematiqueTable.actionImpactId), + ) + .leftJoin( + thematiqueTable, + eq(actionImpactThematiqueTable.thematiqueId, thematiqueTable.id), + ) + .leftJoin( + actionImpactPanierTable, + and( + eq(actionImpactPanierTable.actionId, actionImpactTable.id), + eq(actionImpactPanierTable.panierId, panierId), + ), + ) + .where(and(...where)); + + return Object.values( + actions.reduce( + (acc, row) => { + const actionId = row.action.id; + + if (!acc[actionId]) { + acc[actionId] = { + action: { + ...row.action, + rex: Array.isArray(row.action.rex) ? row.action.rex : [], + subventionsMobilisables: Array.isArray( + row.action.subventionsMobilisables, + ) + ? row.action.subventionsMobilisables + : [], + ressourcesExternes: Array.isArray(row.action.ressourcesExternes) + ? row.action.ressourcesExternes + : [], + }, + isinpanier: !!row.isInPanier, + statut: row.statut || null, + thematiques: [], + }; + } + + if (row.thematique) { + acc[actionId].thematiques.push(row.thematique); + } + + return acc; + }, + {} as Record, + ), + ); + } + + /** + * Récupère le panier complet et les actions à impacts vis à vis du panier + * @param panierId identifiant d'un panier + * @param thematiqueIds identifiants des thématiques voulus + * @param niveauxBudget identifiants des niveaux de budgets voulus + * @param niveauxTemps identifiants des niveaux de temps voulus + * @return les actions à impact filtrées + */ + async getPanierComplet( + panierId: string, + thematiqueIds: number[], + niveauxBudget: number[], + niveauxTemps: number[], + ): Promise { + const paniersResult = await this.databaseService.db + .select() + .from(panierTable) + .leftJoin( + actionImpactPanierTable, + eq(actionImpactPanierTable.panierId, panierTable.id), + ) + .leftJoin( + actionImpactTable, + eq(actionImpactTable.id, actionImpactPanierTable.actionId), + ) + .leftJoin( + actionImpactThematiqueTable, + eq(actionImpactTable.id, actionImpactThematiqueTable.actionImpactId), + ) + .leftJoin( + thematiqueTable, + eq(actionImpactThematiqueTable.thematiqueId, thematiqueTable.id), + ) + .where(eq(panierTable.id, panierId)); + + if (paniersResult.length > 0) { + const actionsFiltrees = await this.getActionImpactsFiltered( + panierId, + thematiqueIds, + niveauxBudget, + niveauxTemps, + ); + return { + ...paniersResult[0].panier, + contenu: Object.values( + paniersResult + .filter((f) => f.action_impact !== null) + .reduce( + (acc, row) => { + const actionId = row.action_impact!.id; + + if (!acc[actionId]) { + acc[actionId] = { + ...row.action_impact!, + rex: Array.isArray(row.action_impact!.rex) + ? row.action_impact!.rex + : [], + subventionsMobilisables: Array.isArray( + row.action_impact!.subventionsMobilisables, + ) + ? row.action_impact!.subventionsMobilisables + : [], + ressourcesExternes: Array.isArray( + row.action_impact!.ressourcesExternes, + ) + ? row.action_impact!.ressourcesExternes + : [], + thematiques: [], + }; + } + + if (row.thematique) { + acc[actionId].thematiques.push(row.thematique); + } + + return acc; + }, + {} as Record, + ), + ), + states: actionsFiltrees, + }; + } + return null; + } + + /** + * Met à jour les données du panier depuis directus + * @param tokenInfo token de l'utilisateur + */ + async majPanierFromDirectus(tokenInfo: SupabaseJwtPayload) { + if (tokenInfo.role !== SupabaseRole.SERVICE_ROLE) { + throw new UnauthorizedException(`Droits insuffisants`); + } + // Met à jour les partenaires possibles du panier provenant de directus + await this.panierPartenaireService.majPartenairePanierFromDirectus(); + // Récupère des données utile à la mise à jour des actions à impact + const datas: Datas = { + // Besoin de récupérer les indicateurs car directus a pour identifiant l'identifiant_referentiel ... + // ... et non l'id + indicateurs: await this.indicateurService.getIndicateursPredefinisMap(), + // Besoin de récupérer les sous thématiques car les ids entre directus et la BD ne correspondent pas, ... + // ... le lien doit se faire via le nom + sousThematiques: await this.thematiqueService.getSousThematiquesMap(), + sousThematiquesDirectus: + await this.directusService.getSousThematiquesFromDirectus(), + }; + // Récupère les actions à impact provenant de directus + const actions = await this.directusService.getActionsImpactFromDirectus(); + for (const action of actions) { + // Met à jour les actions à impact et les champs associées provenant de directus + await this.actionImpactService.majActionImpactFromDirectus(action, datas); + } + } + + /** + * La liste des collectivités dans lesquelles on peut + * créer un plan à partir d'un panier. + */ + /* + async mesCollectivites(): Promise { + const {data, error} = await this.supabase + .from('mes_collectivites') + .select('collectiviteId, nom, niveau_acces, est_auditeur') + .in('niveau_acces', ['admin', 'edition']) + .returns(); + if (error) throw error; + return data; + }*/ +} diff --git a/backend/src/panier/services/plan-from-panier.service.ts b/backend/src/panier/services/plan-from-panier.service.ts new file mode 100644 index 0000000000..9c594d0163 --- /dev/null +++ b/backend/src/panier/services/plan-from-panier.service.ts @@ -0,0 +1,419 @@ +import { Injectable, Logger } from '@nestjs/common'; +import { and, eq } from 'drizzle-orm'; +import DatabaseService from '../../common/services/database.service'; +import { + actionImpactTable, + ActionImpactTransformeType, +} from '../models/action-impact.table'; +import { axeTable, CreateAxeType } from '../../fiches/models/axe.table'; +import AxeService from '../../fiches/services/axe.service'; +import FicheService from '../../fiches/services/fiche.service'; +import DocumentService from '../../documents/services/document.service'; +import { + panierPartenaireTable, + PanierPartenaireType, +} from '../../taxonomie/models/panier-partenaire.table'; +import { + actionImpactCategorieTable, + ActionImpactCategorieType, +} from '../models/action-impact-categorie.table'; +import { + actionImpactThematiqueTable, + ActionImpactThematiqueType, +} from '../models/action-impact-thematique.table'; +import { + actionImpactSousThematiqueTable, + ActionImpactSousThematiqueType, +} from '../models/action-impact-sous-thematique.table'; +import { + actionImpactFourchetteBudgetaireTable, + ActionImpactFourchetteBudgetaireType, +} from '../models/action-impact-fourchette-budgetaire.table'; +import { + actionImpactIndicateurTable, + ActionImpactIndicateurType, +} from '../models/action-impact-indicateur.table'; +import { + actionImpactEffetAttenduTable, + ActionImpactEffetAttenduType, +} from '../models/action-impact-effet-attendu.table'; +import { + actionImpactActionTable, + ActionImpactActionType, +} from '../models/action-impact-action.table'; +import { actionImpactPartenaireTable } from '../models/action-impact-partenaire.table'; +import { actionImpactPanierTable } from '../models/action-impact-panier.table'; +import { actionImpactStatutTable } from '../models/action-impact-statut.table'; +import { lienType } from '../../documents/models/document-lien.dto'; +import { SupabaseJwtPayload } from '../../auth/models/supabase-jwt.models'; +import { AuthService } from '../../auth/services/auth.service'; +import BrevoService from '../../brevo/service/brevo.service'; +import { BrevoLists } from '../../brevo/models/brevo.models'; +import { FicheActionStatutsEnumType } from '../../fiches/models/fiche-action.table'; + +// Crée un type qui permettra de parcourir facilement les actions +type actionsFromPanier = { + action_impact: ActionImpactTransformeType; + action_impact_thematique: ActionImpactThematiqueType[]; + action_impact_sous_thematique: ActionImpactSousThematiqueType[]; + action_impact_indicateur: ActionImpactIndicateurType[]; + action_impact_effet_attendu: ActionImpactEffetAttenduType[]; + action_impact_action: ActionImpactActionType[]; + panier_partenaire: PanierPartenaireType[]; + action_impact_fourchette_budgetaire: ActionImpactFourchetteBudgetaireType | null; + action_impact_categorie: ActionImpactCategorieType | null; +}; + +const LISTS_TO_REMOVE = [ + BrevoLists.ID_LIST_BREVO_ONBOARDING_GENERAL, + BrevoLists.ID_LIST_BREVO_CREATION_PA, + BrevoLists.ID_LIST_BREVO_SONDAGE_PA_1, + BrevoLists.ID_LIST_BREVO_SONDAGE_PA_2, +]; + +@Injectable() +export default class PlanFromPanierService { + private readonly logger = new Logger(PlanFromPanierService.name); + + constructor( + private readonly databaseService: DatabaseService, + private readonly axeService: AxeService, + private readonly ficheService: FicheService, + private readonly documentService: DocumentService, + private readonly authService: AuthService, + private readonly brevoService: BrevoService, + ) {} + + /** + * Crée un plan d'action pour la collectivité à partir d'un panier + * @param tokenInfo token de l'utilisateur + * @param collectiviteId identifiant de la collectivité + * @param panierId identifiant du panier + * @param planId identifiant du plan dans lequel ajouter les fiches, indéfini pour créer un nouveau plan + * @return identifiant du plan d'actions créé + */ + async addPlanFromPanier( + tokenInfo: SupabaseJwtPayload, + collectiviteId: number, + panierId: string, + planId?: number, + ): Promise { + // Vérifie les droits + await this.authService.verifieAccesRestreintCollectivite( + tokenInfo, + collectiviteId, + ); + let axeId; + if (!planId) { + // Crée le plan + const axe: CreateAxeType = { + collectiviteId: collectiviteId, + nom: "Plan d'action à impact", + panierId: panierId, + }; + axeId = await this.axeService.createOrReturnAxeId(axe); + } else { + axeId = planId; + } + // Fait le lien entre le plan et le panier + await this.databaseService.db + .update(axeTable) + .set({ panierId: panierId }) + .where(eq(axeTable.id, axeId)); + + const actions = await this.getActionsFromPanier(panierId); + + // Pour chaque action à impact du panier + for (const action of actions) { + await this.addFicheFromActionImpact(collectiviteId, axeId, action); + } + // Envoie à Brevo de l'utilisateur + await this.sendUserPaiToBrevo(tokenInfo); + return axeId; + } + + /** + * Récupère les actions du panier ainsi que leurs informations liées + * @param panierId identifiant du panier + * @return les actions à impact et leurs informations liées + */ + private async getActionsFromPanier( + panierId: string, + ): Promise { + const result = await this.databaseService.db + .select() + .from(actionImpactTable) + .innerJoin( + actionImpactPanierTable, + eq(actionImpactTable.id, actionImpactPanierTable.actionId), + ) + .leftJoin( + actionImpactThematiqueTable, + eq(actionImpactTable.id, actionImpactThematiqueTable.actionImpactId), + ) + .leftJoin( + actionImpactSousThematiqueTable, + eq( + actionImpactTable.id, + actionImpactSousThematiqueTable.actionImpactId, + ), + ) + .leftJoin( + actionImpactFourchetteBudgetaireTable, + eq( + actionImpactTable.fourchetteBudgetaire, + actionImpactFourchetteBudgetaireTable.niveau, + ), + ) + .leftJoin( + actionImpactIndicateurTable, + eq(actionImpactTable.id, actionImpactIndicateurTable.actionImpactId), + ) + .leftJoin( + actionImpactEffetAttenduTable, + eq(actionImpactTable.id, actionImpactEffetAttenduTable.actionImpactId), + ) + .leftJoin( + actionImpactActionTable, + eq(actionImpactTable.id, actionImpactActionTable.actionImpactId), + ) + .leftJoin( + actionImpactPartenaireTable, + eq(actionImpactTable.id, actionImpactPartenaireTable.actionImpactId), + ) + .leftJoin( + panierPartenaireTable, + eq(panierPartenaireTable.id, actionImpactPartenaireTable.partenaireId), + ) + .leftJoin( + actionImpactStatutTable, + and( + eq(actionImpactTable.id, actionImpactStatutTable.actionId), + eq( + actionImpactPanierTable.panierId, + actionImpactStatutTable.panierId, + ), + ), + ) + .leftJoin( + actionImpactCategorieTable, + eq(actionImpactStatutTable.categorieId, actionImpactCategorieTable.id), + ) + .where(eq(actionImpactPanierTable.panierId, panierId)); + + // Transforme le résultat de la requête en des objects + // de type addPlanFromPanierResult plus facile à manipuler + return Object.values( + result.reduce( + (acc, row) => { + const actionId = row.action_impact.id; + + if (!acc[actionId]) { + acc[actionId] = { + action_impact: { + ...row.action_impact, + rex: Array.isArray(row.action_impact.rex) + ? row.action_impact.rex + : [], + subventionsMobilisables: Array.isArray( + row.action_impact.subventionsMobilisables, + ) + ? row.action_impact.subventionsMobilisables + : [], + ressourcesExternes: Array.isArray( + row.action_impact.ressourcesExternes, + ) + ? row.action_impact.ressourcesExternes + : [], + }, + action_impact_thematique: [], + action_impact_sous_thematique: [], + action_impact_indicateur: [], + action_impact_effet_attendu: [], + action_impact_action: [], + panier_partenaire: [], + action_impact_fourchette_budgetaire: + row.action_impact_fourchette_budgetaire, + action_impact_categorie: row.action_impact_categorie, + }; + } + + if (row.action_impact_thematique) { + acc[actionId].action_impact_thematique.push( + row.action_impact_thematique, + ); + } + if (row.action_impact_sous_thematique) { + acc[actionId].action_impact_sous_thematique.push( + row.action_impact_sous_thematique, + ); + } + if (row.action_impact_indicateur) { + acc[actionId].action_impact_indicateur.push( + row.action_impact_indicateur, + ); + } + if (row.action_impact_effet_attendu) { + acc[actionId].action_impact_effet_attendu.push( + row.action_impact_effet_attendu, + ); + } + if (row.action_impact_action) { + acc[actionId].action_impact_action.push(row.action_impact_action); + } + if (row.panier_partenaire) { + acc[actionId].panier_partenaire.push(row.panier_partenaire); + } + + return acc; + }, + {} as Record, + ), + ); + } + + /** + * Crée une fiche depuis une action à impact + * @param collectiviteId identifiant de la collectivité + * @param axeId identifiant du plan + * @param action action à impact et ses informations liées + */ + private async addFicheFromActionImpact( + collectiviteId: number, + axeId: number, + action: actionsFromPanier, + ) { + // On créé une fiche + const ficheId = await this.ficheService.createFiche({ + titre: action.action_impact.titre, + description: action.action_impact.description, + collectiviteId: collectiviteId, + financements: action.action_impact_fourchette_budgetaire?.nom || null, + /*statut: ['en_cours', 'realise'].includes( + action.action_impact_categorie?.id || '', + ) + ? Object.values(FicheActionStatutsEnumType) + .find((enumValue) => + enumValue === action.action_impact_categorie!.nom) + : FicheActionStatutsEnumType.A_VENIR,*/ + }); + // TODO faire l'ajout du statut + // On ajoute la fiche au plan + await this.axeService.addFicheAction(ficheId, axeId); + // On fait le lien vers l'action à impact à l'origine de la fiche + await this.ficheService.addActionImpact(ficheId, action.action_impact.id); + // On ajoute les thématiques + if (action.action_impact_thematique) { + for (const thematique of action.action_impact_thematique) { + await this.ficheService.addThematique(ficheId, thematique.thematiqueId); + } + } + // On ajoute les sous-thématiques + if (action.action_impact_sous_thematique) { + for (const thematique of action.action_impact_sous_thematique) { + await this.ficheService.addSousThematique( + ficheId, + thematique.sousThematiqueId, + ); + } + } + // On ajoute les indicateurs + if (action.action_impact_indicateur) { + for (const indicateur of action.action_impact_indicateur) { + await this.ficheService.addIndicateur(ficheId, indicateur.indicateurId); + } + } + // On ajoute les effets attendus + if (action.action_impact_effet_attendu) { + for (const effet of action.action_impact_effet_attendu) { + await this.ficheService.addEffetAttendu(ficheId, effet.effetAttenduId); + } + } + // On ajoute les actions + if (action.action_impact_action) { + for (const actionRef of action.action_impact_action) { + await this.ficheService.addActionReferentiel( + ficheId, + actionRef.actionId, + ); + } + } + + // On ajoute les liens ressources + if (action.action_impact.ressourcesExternes) { + for (const ressource of action.action_impact.ressourcesExternes) { + await this.documentService.createLienAnnexe( + ficheId, + ressource as lienType, + collectiviteId, + ); + } + } + if (action.action_impact.rex) { + for (const ressource of action.action_impact.rex) { + await this.documentService.createLienAnnexe( + ficheId, + ressource as lienType, + collectiviteId, + ); + } + } + + // On ajoute les partenaires + if (action.panier_partenaire) { + for (const partenaire of action.panier_partenaire) { + await this.ficheService.addPartenaireByNom( + ficheId, + partenaire.nom, + collectiviteId, + ); + } + } + } + + /** + * Envoie l'utilisateur qui a crée un plan depuis le plan d'action à Brevo si c'est un utilisateur récent + * @param tokenInfo + */ + private async sendUserPaiToBrevo(tokenInfo: SupabaseJwtPayload) { + const email = tokenInfo.email; + const user = await this.authService.getUserCrmInfo(tokenInfo); + const hier = new Date(); + hier.setDate(hier.getDate() - 1); + // On envoie l'utilisateur que si c'est un nouvel utilisateur + if (user && user.creation && new Date(user.creation) > hier) { + const emails = []; + if (email) { + // Vérifie si le contact existe déjà dans Brevo + const contactJson = await this.brevoService.getContactByEmail(email); + + if (contactJson) { + this.logger.log('get contact' + contactJson.email); + // Vérifie si le contact appartient déjà à la liste + if ( + !contactJson.listIds.includes( + BrevoLists.ID_LIST_BREVO_ONBOARDING_PAI, + ) + ) { + emails.push(email); + } + // Vérifie si le contact appartient aux autres listes, et si oui, les enlève + for (const listId of LISTS_TO_REMOVE) { + if (contactJson.listIds.includes(listId)) { + await this.brevoService.removeContactsFromList(emails, listId); + this.logger.log( + 'remove contact' + contactJson.email + ' from list ' + listId, + ); + } + } + } else { + // Ajoute le contact + if (await this.brevoService.addContact(user)) { + emails.push(email); + this.logger.log('add contact ' + email + ' to Brevo'); + } + } + } + } + } +} From 71a86357031fd901490debba5674efae3365fa27 Mon Sep 17 00:00:00 2001 From: Amandine Date: Thu, 12 Sep 2024 18:33:12 +0200 Subject: [PATCH 14/22] Front - Panier - WIP - Change le realtime de supabase par websocket --- packages/panier/components/PanierRealtime/index.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/panier/components/PanierRealtime/index.tsx b/packages/panier/components/PanierRealtime/index.tsx index c70890b4f2..66f24852ec 100644 --- a/packages/panier/components/PanierRealtime/index.tsx +++ b/packages/panier/components/PanierRealtime/index.tsx @@ -58,9 +58,14 @@ const PanierRealtime = ({ }, [panier.collectivite_preset, setCollectiviteId]); useEffect(() => { - const channel = panierAPI.listenToPanierUpdates(panier.id, router.refresh); + const socket: Socket = io('http://localhost:3000'); + socket.on('panierUpdate', (panierId) => { + if (panierId === panier.id) { + router.refresh(); + } + }); return () => { - supabase.removeChannel(channel); + socket.disconnect(); }; }, [router, panier.id, setUser]); From 9418d9d26969ff50d860a8f106437fcad1f6c900 Mon Sep 17 00:00:00 2001 From: Amandine Date: Wed, 18 Sep 2024 17:59:10 +0200 Subject: [PATCH 15/22] =?UTF-8?q?Backend=20-=20Ajoute=20les=20cat=C3=A9gor?= =?UTF-8?q?ies=20FNV?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/taxonomie/models/categorie-fnv.table.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 backend/src/taxonomie/models/categorie-fnv.table.ts diff --git a/backend/src/taxonomie/models/categorie-fnv.table.ts b/backend/src/taxonomie/models/categorie-fnv.table.ts new file mode 100644 index 0000000000..6e96d383c2 --- /dev/null +++ b/backend/src/taxonomie/models/categorie-fnv.table.ts @@ -0,0 +1,11 @@ +import { pgTable, serial, text } from 'drizzle-orm/pg-core'; +import { InferSelectModel } from 'drizzle-orm'; +import { createSelectSchema } from 'drizzle-zod'; + +export const categorieFNVTable = pgTable('categorie_fnv', { + id: serial('id').primaryKey(), + nom: text('nom').notNull(), +}); +export type CategorieFNVType = InferSelectModel; + +export const categorieFNVSchema = createSelectSchema(categorieFNVTable); From 39917d3929f2473c5ac561733d22297455dbc95a Mon Sep 17 00:00:00 2001 From: Amandine Date: Fri, 20 Sep 2024 11:02:23 +0200 Subject: [PATCH 16/22] =?UTF-8?q?Backend-=20S=C3=A9pare=20les=20tables=20l?= =?UTF-8?q?i=C3=A9es=20aux=20collectivit=C3=A9s=20dans=20des=20fichiers=20?= =?UTF-8?q?diff=C3=A9rents?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../models/collectivite-test.table.ts | 10 +++ .../models/collectivite.models.ts | 68 ------------------- .../models/collectivite.table.ts | 21 ++++++ .../src/collectivites/models/commune.table.ts | 14 ++++ .../src/collectivites/models/epci.table.ts | 38 +++++++++++ .../models/groupement-collectivite.table.ts | 22 ++++++ .../collectivites/models/groupement.models.ts | 28 -------- .../collectivites/models/groupement.table.ts | 9 +++ .../services/collectivites.service.ts | 14 ++-- .../services/groupements.service.ts | 8 +-- 10 files changed, 124 insertions(+), 108 deletions(-) create mode 100644 backend/src/collectivites/models/collectivite-test.table.ts delete mode 100644 backend/src/collectivites/models/collectivite.models.ts create mode 100644 backend/src/collectivites/models/collectivite.table.ts create mode 100644 backend/src/collectivites/models/commune.table.ts create mode 100644 backend/src/collectivites/models/epci.table.ts create mode 100644 backend/src/collectivites/models/groupement-collectivite.table.ts delete mode 100644 backend/src/collectivites/models/groupement.models.ts create mode 100644 backend/src/collectivites/models/groupement.table.ts diff --git a/backend/src/collectivites/models/collectivite-test.table.ts b/backend/src/collectivites/models/collectivite-test.table.ts new file mode 100644 index 0000000000..c403a2bff5 --- /dev/null +++ b/backend/src/collectivites/models/collectivite-test.table.ts @@ -0,0 +1,10 @@ +import { integer, pgTable, serial, varchar } from 'drizzle-orm/pg-core'; +import { collectiviteTable } from './collectivite.table'; + +export const collectiviteTestTable = pgTable('collectivite_test', { + id: serial('id').primaryKey().notNull(), + collectiviteId: integer('collectivite_id').references( + () => collectiviteTable.id, + ), + nom: varchar('nom', { length: 300 }).notNull(), +}); diff --git a/backend/src/collectivites/models/collectivite.models.ts b/backend/src/collectivites/models/collectivite.models.ts deleted file mode 100644 index 72d755b59b..0000000000 --- a/backend/src/collectivites/models/collectivite.models.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { InferInsertModel, InferSelectModel, sql } from 'drizzle-orm'; -import { - boolean, - integer, - pgEnum, - pgTable, - serial, - timestamp, - varchar, -} from 'drizzle-orm/pg-core'; -import { createInsertSchema, createSelectSchema } from 'drizzle-zod'; - -// TODO: create domain siren as varchar(9) check ( value ~ '^\d{9}$' ); -// TODO: create domain codegeo as varchar(5); - -export const epciNatureEnum = pgEnum('nature', [ - 'SMF', - 'CU', - 'CC', - 'SIVOM', - 'POLEM', - 'METRO', - 'SMO', - 'CA', - 'EPT', - 'SIVU', - 'PETR', -]); - -export const collectiviteTable = pgTable('collectivite', { - id: serial('id').primaryKey(), - modified_at: timestamp('modified_at', { withTimezone: true }) - .default(sql.raw(`CURRENT_TIMESTAMP`)) - .notNull(), - created_at: timestamp('created_at', { withTimezone: true }) - .default(sql.raw(`CURRENT_TIMESTAMP`)) - .notNull(), - access_restreint: boolean('access_restreint'), -}); -export const collectiviteSchema = createSelectSchema(collectiviteTable); -export const createCollectiviteSchema = createInsertSchema(collectiviteTable); -export type CollectiviteType = InferSelectModel; -export type CreateCollectiviteType = InferInsertModel; - -export const epciTable = pgTable('epci', { - id: serial('id').primaryKey(), - collectivite_id: integer('collectivite_id') - .notNull() - .references(() => collectiviteTable.id), - nom: varchar('nom', { length: 300 }).notNull(), - siren: varchar('siren', { length: 9 }).unique().notNull(), - nature: epciNatureEnum('nature').notNull(), -}); -export const epciSchema = createSelectSchema(epciTable); -export const createEpciSchema = createInsertSchema(epciTable); -export type EpciType = InferSelectModel; -export type CreateEpciType = InferInsertModel; - -export const communeTable = pgTable('commune', { - id: serial('id').primaryKey(), - collectivite_id: integer('collectivite_id') - .notNull() - .references(() => collectiviteTable.id), - nom: varchar('nom', { length: 300 }).notNull(), - code: varchar('code', { length: 5 }).unique().notNull(), // TODO: domain codegeo -}); -export type CommuneType = InferSelectModel; -export type CreateCommuneType = InferInsertModel; diff --git a/backend/src/collectivites/models/collectivite.table.ts b/backend/src/collectivites/models/collectivite.table.ts new file mode 100644 index 0000000000..8140360c69 --- /dev/null +++ b/backend/src/collectivites/models/collectivite.table.ts @@ -0,0 +1,21 @@ +import { InferInsertModel, InferSelectModel, sql } from 'drizzle-orm'; +import { boolean, pgTable, serial, timestamp } from 'drizzle-orm/pg-core'; +import { createInsertSchema, createSelectSchema } from 'drizzle-zod'; + +// TODO: create domain siren as varchar(9) check ( value ~ '^\d{9}$' ); +// TODO: create domain codegeo as varchar(5); + +export const collectiviteTable = pgTable('collectivite', { + id: serial('id').primaryKey(), + modifiedAt: timestamp('modified_at', { withTimezone: true }) + .default(sql.raw(`CURRENT_TIMESTAMP`)) + .notNull(), + createdAt: timestamp('created_at', { withTimezone: true }) + .default(sql.raw(`CURRENT_TIMESTAMP`)) + .notNull(), + accessRestreint: boolean('access_restreint'), +}); +export const collectiviteSchema = createSelectSchema(collectiviteTable); +export const createCollectiviteSchema = createInsertSchema(collectiviteTable); +export type CollectiviteType = InferSelectModel; +export type CreateCollectiviteType = InferInsertModel; diff --git a/backend/src/collectivites/models/commune.table.ts b/backend/src/collectivites/models/commune.table.ts new file mode 100644 index 0000000000..92aa0588ae --- /dev/null +++ b/backend/src/collectivites/models/commune.table.ts @@ -0,0 +1,14 @@ +import { integer, pgTable, serial, varchar } from 'drizzle-orm/pg-core'; +import { InferInsertModel, InferSelectModel } from 'drizzle-orm'; +import { collectiviteTable } from './collectivite.table'; + +export const communeTable = pgTable('commune', { + id: serial('id').primaryKey(), + collectiviteId: integer('collectivite_id') + .notNull() + .references(() => collectiviteTable.id), + nom: varchar('nom', { length: 300 }).notNull(), + code: varchar('code', { length: 5 }).unique().notNull(), // TODO: domain codegeo +}); +export type CommuneType = InferSelectModel; +export type CreateCommuneType = InferInsertModel; diff --git a/backend/src/collectivites/models/epci.table.ts b/backend/src/collectivites/models/epci.table.ts new file mode 100644 index 0000000000..68b5628acb --- /dev/null +++ b/backend/src/collectivites/models/epci.table.ts @@ -0,0 +1,38 @@ +import { InferInsertModel, InferSelectModel } from 'drizzle-orm'; +import { + integer, + pgEnum, + pgTable, + serial, + varchar, +} from 'drizzle-orm/pg-core'; +import { createInsertSchema, createSelectSchema } from 'drizzle-zod'; +import { collectiviteTable } from './collectivite.table'; + +export const epciNatureEnum = pgEnum('nature', [ + 'SMF', + 'CU', + 'CC', + 'SIVOM', + 'POLEM', + 'METRO', + 'SMO', + 'CA', + 'EPT', + 'SIVU', + 'PETR', +]); + +export const epciTable = pgTable('epci', { + id: serial('id').primaryKey(), + collectiviteId: integer('collectivite_id') + .notNull() + .references(() => collectiviteTable.id), + nom: varchar('nom', { length: 300 }).notNull(), + siren: varchar('siren', { length: 9 }).unique().notNull(), + nature: epciNatureEnum('nature').notNull(), +}); +export const epciSchema = createSelectSchema(epciTable); +export const createEpciSchema = createInsertSchema(epciTable); +export type EpciType = InferSelectModel; +export type CreateEpciType = InferInsertModel; diff --git a/backend/src/collectivites/models/groupement-collectivite.table.ts b/backend/src/collectivites/models/groupement-collectivite.table.ts new file mode 100644 index 0000000000..68149b4426 --- /dev/null +++ b/backend/src/collectivites/models/groupement-collectivite.table.ts @@ -0,0 +1,22 @@ +import { integer, pgTable } from 'drizzle-orm/pg-core'; +import { collectiviteTable } from './collectivite.table'; +import { InferInsertModel, InferSelectModel } from 'drizzle-orm'; +import { groupementTable } from './groupement.table'; + +export const groupementCollectiviteTable = pgTable('groupement_collectivite', { + groupementId: integer('groupement_id').references(() => groupementTable.id, { + onDelete: 'cascade', + }), + collectiviteId: integer('collectivite_id').references( + () => collectiviteTable.id, + { + onDelete: 'cascade', + }, + ), +}); +export type GroupementCollectiviteType = InferSelectModel< + typeof groupementCollectiviteTable +>; +export type CreateGroupementCollectiviteType = InferInsertModel< + typeof groupementCollectiviteTable +>; diff --git a/backend/src/collectivites/models/groupement.models.ts b/backend/src/collectivites/models/groupement.models.ts deleted file mode 100644 index b3d8ab3c6a..0000000000 --- a/backend/src/collectivites/models/groupement.models.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { InferInsertModel, InferSelectModel } from 'drizzle-orm'; -import { integer, pgTable, serial, text } from 'drizzle-orm/pg-core'; -import { collectiviteTable } from './collectivite.models'; - -export const groupementTable = pgTable('groupement', { - id: serial('id').primaryKey(), - nom: text('nom').notNull(), -}); -export type GroupementType = InferSelectModel; -export type CreateGroupementType = InferInsertModel; - -export const groupementCollectiviteTable = pgTable('groupement_collectivite', { - groupement_id: integer('groupement_id').references(() => groupementTable.id, { - onDelete: 'cascade', - }), - collectivite_id: integer('collectivite_id').references( - () => collectiviteTable.id, - { - onDelete: 'cascade', - }, - ), -}); -export type GroupementCollectiviteType = InferSelectModel< - typeof groupementCollectiviteTable ->; -export type CreateGroupementCollectiviteType = InferInsertModel< - typeof groupementCollectiviteTable ->; diff --git a/backend/src/collectivites/models/groupement.table.ts b/backend/src/collectivites/models/groupement.table.ts new file mode 100644 index 0000000000..fb065eed3b --- /dev/null +++ b/backend/src/collectivites/models/groupement.table.ts @@ -0,0 +1,9 @@ +import { InferInsertModel, InferSelectModel } from 'drizzle-orm'; +import { pgTable, serial, text } from 'drizzle-orm/pg-core'; + +export const groupementTable = pgTable('groupement', { + id: serial('id').primaryKey(), + nom: text('nom').notNull(), +}); +export type GroupementType = InferSelectModel; +export type CreateGroupementType = InferInsertModel; diff --git a/backend/src/collectivites/services/collectivites.service.ts b/backend/src/collectivites/services/collectivites.service.ts index 5aacfff365..4e494486d4 100644 --- a/backend/src/collectivites/services/collectivites.service.ts +++ b/backend/src/collectivites/services/collectivites.service.ts @@ -1,11 +1,9 @@ import { Injectable, Logger, NotFoundException } from '@nestjs/common'; import { eq } from 'drizzle-orm'; import DatabaseService from '../../common/services/database.service'; -import { - collectiviteTable, - communeTable, - epciTable, -} from '../models/collectivite.models'; +import { collectiviteTable } from '../models/collectivite.table'; +import { epciTable } from '../models/epci.table'; +import { communeTable } from '../models/commune.table'; @Injectable() export default class CollectivitesService { @@ -24,9 +22,9 @@ export default class CollectivitesService { .from(collectiviteTable) .leftJoin( communeTable, - eq(communeTable.collectivite_id, collectiviteTable.id), + eq(communeTable.collectiviteId, collectiviteTable.id), ) - .leftJoin(epciTable, eq(epciTable.collectivite_id, collectiviteTable.id)) + .leftJoin(epciTable, eq(epciTable.collectiviteId, collectiviteTable.id)) .where(eq(collectiviteTable.id, collectiviteId)); if (!collectiviteByIdResult?.length) { throw new NotFoundException( @@ -47,7 +45,7 @@ export default class CollectivitesService { const epciByIdResult = await this.databaseService.db .select() .from(epciTable) - .where(eq(epciTable.collectivite_id, collectiviteId)); + .where(eq(epciTable.collectiviteId, collectiviteId)); if (!epciByIdResult?.length) { throw new NotFoundException( `EPCI avec l'identifiant de collectivite ${collectiviteId} introuvable`, diff --git a/backend/src/collectivites/services/groupements.service.ts b/backend/src/collectivites/services/groupements.service.ts index 29cb2ceff3..79935ccda0 100644 --- a/backend/src/collectivites/services/groupements.service.ts +++ b/backend/src/collectivites/services/groupements.service.ts @@ -7,11 +7,11 @@ import { } from '@nestjs/common'; import { eq } from 'drizzle-orm'; import DatabaseService from '../../common/services/database.service'; +import { groupementTable } from '../models/groupement.table'; import { CreateGroupementCollectiviteType, groupementCollectiviteTable, - groupementTable, -} from '../models/groupement.models'; +} from '../models/groupement-collectivite.table'; @Injectable() export default class GroupementsService { @@ -48,8 +48,8 @@ export default class GroupementsService { `Ajout de la collectivite ${collectiviteId} au groupement ${groupementId}`, ); const createGroupementCollectivite: CreateGroupementCollectiviteType = { - collectivite_id: collectiviteId, - groupement_id: groupementId, + collectiviteId: collectiviteId, + groupementId: groupementId, }; await this.databaseService.db From ec76f944348f632d02da92a08c767dc2bfd28b3e Mon Sep 17 00:00:00 2001 From: Amandine Date: Fri, 20 Sep 2024 11:04:28 +0200 Subject: [PATCH 17/22] Backend - Adapte les fichiers de trajectoires aux nouvelles conventions de nommage --- .../controllers/trajectoires.controller.ts | 42 +- .../models/calcultrajectoire.models.ts | 5 +- .../routers/trajectoires.router.ts | 2 +- .../trajectoires-data.service.spec.ts | 142 +- .../services/trajectoires-data.service.ts | 151 +- .../trajectoires-spreadsheet.service.ts | 46 +- .../services/trajectoires-xlsx.service.ts | 53 +- .../trajectoire-snbc-calcul-retour.ts | 2722 ++++++++--------- .../indicateurs/trajectoire-snbc.e2e-spec.ts | 4 +- 9 files changed, 1579 insertions(+), 1588 deletions(-) diff --git a/backend/src/indicateurs/controllers/trajectoires.controller.ts b/backend/src/indicateurs/controllers/trajectoires.controller.ts index f60fba0696..09339de31c 100644 --- a/backend/src/indicateurs/controllers/trajectoires.controller.ts +++ b/backend/src/indicateurs/controllers/trajectoires.controller.ts @@ -12,7 +12,6 @@ import { ApiOkResponse, ApiResponse, ApiTags } from '@nestjs/swagger'; import { NextFunction, Response } from 'express'; import { PublicEndpoint } from '../../auth/decorators/public-endpoint.decorator'; import { TokenInfo } from '../../auth/decorators/token-info.decorators'; -import type { SupabaseJwtPayload } from '../../auth/models/auth.models'; import { CollectiviteRequestClass } from '../../collectivites/models/collectivite.request'; import { calculTrajectoireRequestSchema, @@ -24,26 +23,27 @@ import { import TrajectoiresDataService from '../services/trajectoires-data.service'; import TrajectoiresSpreadsheetService from '../services/trajectoires-spreadsheet.service'; import TrajectoiresXlsxService from '../services/trajectoires-xlsx.service'; +import type { SupabaseJwtPayload } from '../../auth/models/supabase-jwt.models'; /** * 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 + calculTrajectoireResponseSchema, ) {} export class CalculTrajectoireRequestClass extends createZodDto( - calculTrajectoireRequestSchema + calculTrajectoireRequestSchema, ) {} export class ModeleTrajectoireTelechargementRequestClass extends createZodDto( - modeleTrajectoireTelechargementRequestSchema + modeleTrajectoireTelechargementRequestSchema, ) {} export class VerificationTrajectoireRequestClass extends createZodDto( - verificationTrajectoireRequestSchema + verificationTrajectoireRequestSchema, ) {} export class VerificationDonneesSNBCResponseClass extends createZodDto( - verificationDonneesSNBCResponseSchema + verificationDonneesSNBCResponseSchema, ) {} @ApiTags('Trajectoires') @@ -54,23 +54,23 @@ export class TrajectoiresController { constructor( private readonly trajectoiresDataService: TrajectoiresDataService, private readonly trajectoiresSpreadsheetService: TrajectoiresSpreadsheetService, - private readonly trajectoiresXlsxService: TrajectoiresXlsxService + private readonly trajectoiresXlsxService: TrajectoiresXlsxService, ) {} @Get('') @ApiResponse({ type: CalculTrajectoireResponseClass }) async calculeTrajectoireSnbc( @Query() request: CalculTrajectoireRequestClass, - @TokenInfo() tokenInfo: SupabaseJwtPayload + @TokenInfo() tokenInfo: SupabaseJwtPayload, ): Promise { this.logger.log( - `Calcul de la trajectoire SNBC pour la collectivité ${request.collectivite_id}` + `Calcul de la trajectoire SNBC pour la collectivité ${request.collectivite_id}`, ); // eslint-disable-next-line @typescript-eslint/no-unused-vars const { spreadsheet_id, ...response } = await this.trajectoiresSpreadsheetService.calculeTrajectoireSnbc( request, - tokenInfo + tokenInfo, ); return response; } @@ -78,15 +78,15 @@ export class TrajectoiresController { @Delete('') async deleteTrajectoireSnbc( @Query() request: CollectiviteRequestClass, - @TokenInfo() tokenInfo: SupabaseJwtPayload + @TokenInfo() tokenInfo: SupabaseJwtPayload, ): Promise { this.logger.log( - `Suppression de la trajectoire SNBC pour la collectivité ${request.collectivite_id}` + `Suppression de la trajectoire SNBC pour la collectivité ${request.collectivite_id}`, ); await this.trajectoiresDataService.deleteTrajectoireSnbc( request.collectivite_id, undefined, - tokenInfo + tokenInfo, ); } @@ -99,13 +99,13 @@ export class TrajectoiresController { downloadModeleSnbc( @Query() request: ModeleTrajectoireTelechargementRequestClass, @Res() res: Response, - @Next() next: NextFunction + @Next() next: NextFunction, ) { this.logger.log(`Téléchargement du modele de trajectoire SNBC`); this.trajectoiresXlsxService.downloadModeleTrajectoireSnbc( request, res, - next + next, ); } @@ -118,16 +118,16 @@ export class TrajectoiresController { @Query() request: CollectiviteRequestClass, @TokenInfo() tokenInfo: SupabaseJwtPayload, @Res() res: Response, - @Next() next: NextFunction + @Next() next: NextFunction, ) { this.logger.log( - `Téléchargement de la trajectoire SNBC pour la collectivité ${request.collectivite_id}` + `Téléchargement de la trajectoire SNBC pour la collectivité ${request.collectivite_id}`, ); this.trajectoiresXlsxService.downloadTrajectoireSnbc( request, tokenInfo, res, - next + next, ); } @@ -139,16 +139,16 @@ export class TrajectoiresController { }) async verificationDonneesSnbc( @Query() request: VerificationTrajectoireRequestClass, - @TokenInfo() tokenInfo: SupabaseJwtPayload + @TokenInfo() tokenInfo: SupabaseJwtPayload, ): Promise { this.logger.log( - `Vérifie la possibilité de lancer le calcul de la trajectoire SNBC pour la collectivité ${request.collectivite_id}` + `Vérifie la possibilité de lancer le calcul de la trajectoire SNBC pour la collectivité ${request.collectivite_id}`, ); // eslint-disable-next-line @typescript-eslint/no-unused-vars const { valeurs, ...response } = await this.trajectoiresDataService.verificationDonneesSnbc( request, - tokenInfo + tokenInfo, ); if (!request.epci_info) { delete response.epci; diff --git a/backend/src/indicateurs/models/calcultrajectoire.models.ts b/backend/src/indicateurs/models/calcultrajectoire.models.ts index 993bbe3362..c33306c3b9 100644 --- a/backend/src/indicateurs/models/calcultrajectoire.models.ts +++ b/backend/src/indicateurs/models/calcultrajectoire.models.ts @@ -1,11 +1,12 @@ import { extendApi, extendZodWithOpenApi } from '@anatine/zod-openapi'; import { z } from 'zod'; -import { epciSchema } from '../../collectivites/models/collectivite.models'; +import { epciSchema } from '../../collectivites/models/epci.table'; import { collectiviteRequestSchema } from '../../collectivites/models/collectivite.request'; import { indicateurAvecValeursSchema, IndicateurValeurType, -} from './indicateur.models'; +} from './indicateur-valeur.table'; + extendZodWithOpenApi(z); export enum CalculTrajectoireReset { diff --git a/backend/src/indicateurs/routers/trajectoires.router.ts b/backend/src/indicateurs/routers/trajectoires.router.ts index 297e9a1189..aaa47c3b64 100644 --- a/backend/src/indicateurs/routers/trajectoires.router.ts +++ b/backend/src/indicateurs/routers/trajectoires.router.ts @@ -3,7 +3,7 @@ import { z } from 'zod'; import { SupabaseJwtPayload, SupabaseRole, -} from '../../auth/models/auth.models'; +} from '../../auth/models/supabase-jwt.models'; import { TrpcService } from '../../trpc/services/trpc.service'; import TrajectoiresSpreadsheetService from '../services/trajectoires-spreadsheet.service'; diff --git a/backend/src/indicateurs/services/trajectoires-data.service.spec.ts b/backend/src/indicateurs/services/trajectoires-data.service.spec.ts index 9d91dcecd7..153aa7585e 100644 --- a/backend/src/indicateurs/services/trajectoires-data.service.spec.ts +++ b/backend/src/indicateurs/services/trajectoires-data.service.spec.ts @@ -3,7 +3,7 @@ import { DateTime } from 'luxon'; import { AuthService } from '../../auth/services/auth.service'; import CollectivitesService from '../../collectivites/services/collectivites.service'; import SheetService from '../../spreadsheets/services/sheet.service'; -import { IndicateurValeurType } from '../models/indicateur.models'; +import { IndicateurValeurType } from '../models/indicateur-valeur.table'; import IndicateursService from './indicateurs.service'; import IndicateurSourcesService from './indicateurSources.service'; import TrajectoiresDataService from './trajectoires-data.service'; @@ -40,67 +40,67 @@ describe('TrajectoiresDataService test', () => { const indicateurValeurs: IndicateurValeurType[] = [ { id: 640644, - collectivite_id: 3894, - indicateur_id: 304, - date_valeur: '2013-01-01', - metadonnee_id: 4, + collectiviteId: 3894, + indicateurId: 304, + dateValeur: '2013-01-01', + metadonneeId: 4, resultat: 9.94, - resultat_commentaire: null, + resultatCommentaire: null, objectif: null, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-07-18T13:25:40.776Z').toJSDate(), - created_at: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-07-18T13:25:40.776Z').toJSDate(), + createdAt: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, { id: 640645, - collectivite_id: 3894, - indicateur_id: 304, - date_valeur: '2014-01-01', - metadonnee_id: 4, + collectiviteId: 3894, + indicateurId: 304, + dateValeur: '2014-01-01', + metadonneeId: 4, resultat: 7.39, - resultat_commentaire: null, + resultatCommentaire: null, objectif: null, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-07-18T13:25:40.776Z').toJSDate(), - created_at: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-07-18T13:25:40.776Z').toJSDate(), + createdAt: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, { id: 640646, - collectivite_id: 3894, - indicateur_id: 304, - date_valeur: '2016-01-01', - metadonnee_id: 4, + collectiviteId: 3894, + indicateurId: 304, + dateValeur: '2016-01-01', + metadonneeId: 4, resultat: 7.47, - resultat_commentaire: null, + resultatCommentaire: null, objectif: null, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-07-18T13:25:40.776Z').toJSDate(), - created_at: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-07-18T13:25:40.776Z').toJSDate(), + createdAt: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, { id: 640647, - collectivite_id: 3894, - indicateur_id: 304, - date_valeur: '2017-01-01', - metadonnee_id: 4, + collectiviteId: 3894, + indicateurId: 304, + dateValeur: '2017-01-01', + metadonneeId: 4, resultat: 7.48, - resultat_commentaire: null, + resultatCommentaire: null, objectif: null, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-07-18T13:25:40.776Z').toJSDate(), - created_at: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-07-18T13:25:40.776Z').toJSDate(), + createdAt: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, ]; @@ -123,51 +123,51 @@ describe('TrajectoiresDataService test', () => { const indicateurValeurs: IndicateurValeurType[] = [ { id: 651923, - collectivite_id: 3903, - indicateur_id: 360, - date_valeur: '2005-01-01', - metadonnee_id: 5, + collectiviteId: 3903, + indicateurId: 360, + dateValeur: '2005-01-01', + metadonneeId: 5, resultat: 0, - resultat_commentaire: null, + resultatCommentaire: null, objectif: null, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), - created_at: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), + createdAt: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, { id: 651924, - collectivite_id: 3903, - indicateur_id: 360, - date_valeur: '2017-01-01', - metadonnee_id: 5, + collectiviteId: 3903, + indicateurId: 360, + dateValeur: '2017-01-01', + metadonneeId: 5, resultat: 0, - resultat_commentaire: null, + resultatCommentaire: null, objectif: null, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), - created_at: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), + createdAt: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, { id: 651925, - collectivite_id: 3903, - indicateur_id: 360, - date_valeur: '2018-01-01', - metadonnee_id: 5, + collectiviteId: 3903, + indicateurId: 360, + dateValeur: '2018-01-01', + metadonneeId: 5, resultat: 0, - resultat_commentaire: null, + resultatCommentaire: null, objectif: null, - objectif_commentaire: null, + objectifCommentaire: null, estimation: null, - modified_at: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), - created_at: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), - modified_by: null, - created_by: null, + modifiedAt: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), + createdAt: DateTime.fromISO('2024-07-10T13:44:47.193Z').toJSDate(), + modifiedBy: null, + createdBy: null, }, ]; diff --git a/backend/src/indicateurs/services/trajectoires-data.service.ts b/backend/src/indicateurs/services/trajectoires-data.service.ts index 1752143999..e5a4ce0990 100644 --- a/backend/src/indicateurs/services/trajectoires-data.service.ts +++ b/backend/src/indicateurs/services/trajectoires-data.service.ts @@ -6,9 +6,9 @@ import { import { isNil } from 'es-toolkit'; import * as _ from 'lodash'; import { DateTime } from 'luxon'; -import { NiveauAcces, SupabaseJwtPayload } from '../../auth/models/auth.models'; +import { NiveauAcces } from '../../auth/models/private-utilisateur-droit.table'; import { AuthService } from '../../auth/services/auth.service'; -import { EpciType } from '../../collectivites/models/collectivite.models'; +import { EpciType } from '../../collectivites/models/epci.table'; import CollectivitesService from '../../collectivites/services/collectivites.service'; import { DonneesARemplirResultType, @@ -18,15 +18,18 @@ import { VerificationDonneesSNBCStatus, VerificationTrajectoireRequestType, } from '../models/calcultrajectoire.models'; +import IndicateursService from './indicateurs.service'; +import IndicateurSourcesService from './indicateurSources.service'; +import { CreateIndicateurSourceType } from '../models/indicateur-source.table'; import { CreateIndicateurSourceMetadonneeType, - CreateIndicateurSourceType, IndicateurSourceMetadonneeType, +} from '../models/indicateur-source-metadonnee.table'; +import { IndicateurValeurAvecMetadonnesDefinition, IndicateurValeurType, -} from '../models/indicateur.models'; -import IndicateursService from './indicateurs.service'; -import IndicateurSourcesService from './indicateurSources.service'; +} from '../models/indicateur-valeur.table'; +import { SupabaseJwtPayload } from '../../auth/models/supabase-jwt.models'; @Injectable() export default class TrajectoiresDataService { @@ -37,7 +40,7 @@ export default class TrajectoiresDataService { 'Indicateurs manquants:'; private readonly OBJECTIF_COMMENTAIRE_REGEXP = new RegExp( - String.raw`${this.OBJECTIF_COMMENTAIRE_SOURCE}\s*(.*?)(?:\s*-\s*${this.OBJECTIF_COMMENTAIRE_INDICATEURS_MANQUANTS}\s*(.*))?$` + String.raw`${this.OBJECTIF_COMMENTAIRE_SOURCE}\s*(.*?)(?:\s*-\s*${this.OBJECTIF_COMMENTAIRE_INDICATEURS_MANQUANTS}\s*(.*))?$`, ); public readonly RARE_SOURCE_ID = 'rare'; @@ -49,11 +52,11 @@ export default class TrajectoiresDataService { }; public readonly SNBC_SOURCE_METADONNEES: CreateIndicateurSourceMetadonneeType = { - source_id: this.SNBC_SOURCE.id, - date_version: DateTime.fromISO('2024-07-11T00:00:00', { + sourceId: this.SNBC_SOURCE.id, + dateVersion: DateTime.fromISO('2024-07-11T00:00:00', { zone: 'utc', }).toJSDate(), - nom_donnees: 'SNBC', + nomDonnees: 'SNBC', diffuseur: 'ADEME', producteur: 'ADEME', // methodologie: '', @@ -205,7 +208,7 @@ export default class TrajectoiresDataService { private readonly collectivitesService: CollectivitesService, private readonly indicateursService: IndicateursService, private readonly indicateurSourcesService: IndicateurSourcesService, - private readonly authService: AuthService + private readonly authService: AuthService, ) {} async getTrajectoireIndicateursMetadonnees(): Promise { @@ -214,36 +217,30 @@ export default class TrajectoiresDataService { this.indicateurSourceMetadonnee = await this.indicateurSourcesService.getIndicateurSourceMetadonnee( this.SNBC_SOURCE.id, - this.SNBC_SOURCE_METADONNEES.date_version + this.SNBC_SOURCE_METADONNEES.dateVersion, ); if (!this.indicateurSourceMetadonnee) { this.logger.log( - `Création de la metadonnée pour la source ${ - this.SNBC_SOURCE.id - } et la date ${this.SNBC_SOURCE_METADONNEES.date_version.toISOString()}` + `Création de la metadonnée pour la source ${this.SNBC_SOURCE.id} et la date ${this.SNBC_SOURCE_METADONNEES.dateVersion.toISOString()}`, ); await this.indicateurSourcesService.upsertIndicateurSource( - this.SNBC_SOURCE + this.SNBC_SOURCE, ); this.indicateurSourceMetadonnee = await this.indicateurSourcesService.createIndicateurSourceMetadonnee( - this.SNBC_SOURCE_METADONNEES + this.SNBC_SOURCE_METADONNEES, ); } } this.logger.log( - `La metadonnée pour la source ${ - this.SNBC_SOURCE.id - } et la date ${this.SNBC_SOURCE_METADONNEES.date_version.toISOString()} existe avec l'identifiant ${ - this.indicateurSourceMetadonnee.id - }` + `La metadonnée pour la source ${this.SNBC_SOURCE.id} et la date ${this.SNBC_SOURCE_METADONNEES.dateVersion.toISOString()} existe avec l'identifiant ${this.indicateurSourceMetadonnee.id}`, ); return this.indicateurSourceMetadonnee; } getObjectifCommentaire( - donneesCalculTrajectoire: DonneesCalculTrajectoireARemplirType + donneesCalculTrajectoire: DonneesCalculTrajectoireARemplirType, ): string { const identifiantsManquants = [ ...donneesCalculTrajectoire.emissions_ges @@ -256,9 +253,7 @@ export default class TrajectoiresDataService { let commentaitre = `${this.OBJECTIF_COMMENTAIRE_SOURCE} ${donneesCalculTrajectoire.source}`; if (identifiantsManquants.length) { - commentaitre += ` - ${ - this.OBJECTIF_COMMENTAIRE_INDICATEURS_MANQUANTS - } ${identifiantsManquants.join(', ')}`; + commentaitre += ` - ${this.OBJECTIF_COMMENTAIRE_INDICATEURS_MANQUANTS} ${identifiantsManquants.join(', ')}`; } return commentaitre; @@ -289,20 +284,20 @@ export default class TrajectoiresDataService { */ async getValeursPourCalculTrajectoire( collectiviteId: number, - forceDonneesCollectivite?: boolean + forceDonneesCollectivite?: boolean, ): Promise { // Récupère les valeurs des indicateurs d'émission pour l'année 2015 (valeur directe ou interpolation) const source = forceDonneesCollectivite ? this.indicateursService.NULL_SOURCE_ID : this.RARE_SOURCE_ID; this.logger.log( - `Récupération des données d'émission GES et de consommation pour la collectivité ${collectiviteId} depuis la source ${source}` + `Récupération des données d'émission GES et de consommation pour la collectivité ${collectiviteId} depuis la source ${source}`, ); const indicateurValeursEmissionsGes = await this.indicateursService.getIndicateursValeurs({ - collectivite_id: collectiviteId, - identifiants_referentiel: _.flatten( - this.SNBC_EMISSIONS_GES_IDENTIFIANTS_REFERENTIEL + collectiviteId: collectiviteId, + identifiantsReferentiel: _.flatten( + this.SNBC_EMISSIONS_GES_IDENTIFIANTS_REFERENTIEL, ), sources: [source], }); @@ -310,15 +305,15 @@ export default class TrajectoiresDataService { // Construit le tableau de valeurs à insérer dans le fichier Spreadsheet const donneesEmissionsGes = this.getValeursARemplirPourIdentifiants( this.SNBC_EMISSIONS_GES_IDENTIFIANTS_REFERENTIEL, - indicateurValeursEmissionsGes + indicateurValeursEmissionsGes, ); // Récupère les valeurs des indicateurs de consommation finale pour l'année 2015 (valeur directe ou interpolation) const indicateurValeursConsommationsFinales = await this.indicateursService.getIndicateursValeurs({ - collectivite_id: collectiviteId, - identifiants_referentiel: _.flatten( - this.SNBC_CONSOMMATIONS_IDENTIFIANTS_REFERENTIEL + collectiviteId: collectiviteId, + identifiantsReferentiel: _.flatten( + this.SNBC_CONSOMMATIONS_IDENTIFIANTS_REFERENTIEL, ), sources: [source], }); @@ -326,15 +321,15 @@ export default class TrajectoiresDataService { // Construit le tableau de valeurs à insérer dans le fichier Spreadsheet const donneesConsommationsFinales = this.getValeursARemplirPourIdentifiants( this.SNBC_CONSOMMATIONS_IDENTIFIANTS_REFERENTIEL, - indicateurValeursConsommationsFinales + indicateurValeursConsommationsFinales, ); // Récupère les valeurs des indicateurs de sequestration pour l'année 2015 (valeur directe ou interpolation) const indicateurValeursSequestration = await this.indicateursService.getIndicateursValeurs({ - collectivite_id: collectiviteId, - identifiants_referentiel: _.flatten( - this.SNBC_SEQUESTRATION_IDENTIFIANTS_REFERENTIEL + collectiviteId: collectiviteId, + identifiantsReferentiel: _.flatten( + this.SNBC_SEQUESTRATION_IDENTIFIANTS_REFERENTIEL, ), sources: [source], }); @@ -342,7 +337,7 @@ export default class TrajectoiresDataService { // Construit le tableau de valeurs à insérer dans le fichier Spreadsheet const donneesSequestration = this.getValeursARemplirPourIdentifiants( this.SNBC_SEQUESTRATION_IDENTIFIANTS_REFERENTIEL, - indicateurValeursSequestration + indicateurValeursSequestration, ); return { source: source, @@ -358,7 +353,7 @@ export default class TrajectoiresDataService { */ getValeursARemplirPourIdentifiants( identifiantsReferentiel: string[][], - indicateurValeurs: IndicateurValeurAvecMetadonnesDefinition[] + indicateurValeurs: IndicateurValeurAvecMetadonnesDefinition[], ): DonneesARemplirResultType { const valeursARemplir: DonneesARemplirValeurType[] = []; const identifiantsReferentielManquants: string[] = []; @@ -373,17 +368,17 @@ export default class TrajectoiresDataService { identifiants.forEach((identifiant) => { const identifiantIndicateurValeurs = indicateurValeurs.filter( (indicateurValeur) => - indicateurValeur.indicateur_definition?.identifiant_referentiel === + indicateurValeur.indicateur_definition?.identifiantReferentiel === identifiant && indicateurValeur.indicateur_valeur.resultat !== null && - indicateurValeur.indicateur_valeur.resultat !== undefined + indicateurValeur.indicateur_valeur.resultat !== undefined, ); const identifiantIndicateurValeur2015 = identifiantIndicateurValeurs.find( (indicateurValeur) => - indicateurValeur.indicateur_valeur.date_valeur === - this.SNBC_DATE_REFERENCE + indicateurValeur.indicateur_valeur.dateValeur === + this.SNBC_DATE_REFERENCE, ); if ( identifiantIndicateurValeur2015 && @@ -397,24 +392,24 @@ export default class TrajectoiresDataService { identifiantIndicateurValeur2015.indicateur_valeur.resultat; if ( !valeurARemplir.date_max || - identifiantIndicateurValeur2015.indicateur_valeur.date_valeur > + identifiantIndicateurValeur2015.indicateur_valeur.dateValeur > valeurARemplir.date_max ) { valeurARemplir.date_max = - identifiantIndicateurValeur2015.indicateur_valeur.date_valeur; + identifiantIndicateurValeur2015.indicateur_valeur.dateValeur; } if ( !valeurARemplir.date_min || - identifiantIndicateurValeur2015.indicateur_valeur.date_valeur < + identifiantIndicateurValeur2015.indicateur_valeur.dateValeur < valeurARemplir.date_min ) { valeurARemplir.date_min = - identifiantIndicateurValeur2015.indicateur_valeur.date_valeur; + identifiantIndicateurValeur2015.indicateur_valeur.dateValeur; } } } else { const interpolationResultat = this.getInterpolationValeur( - identifiantIndicateurValeurs.map((v) => v.indicateur_valeur) + identifiantIndicateurValeurs.map((v) => v.indicateur_valeur), ); if (!interpolationResultat.valeur) { @@ -462,18 +457,18 @@ export default class TrajectoiresDataService { indicateurValeurs.forEach((indicateurValeur) => { if ( - indicateurValeur.date_valeur < this.SNBC_DATE_REFERENCE && + indicateurValeur.dateValeur < this.SNBC_DATE_REFERENCE && (!dateAvant2015 || - (dateAvant2015 && indicateurValeur.date_valeur > dateAvant2015)) + (dateAvant2015 && indicateurValeur.dateValeur > dateAvant2015)) ) { - dateAvant2015 = indicateurValeur.date_valeur; + dateAvant2015 = indicateurValeur.dateValeur; valeurAvant2015 = indicateurValeur.resultat; } else if ( - indicateurValeur.date_valeur > this.SNBC_DATE_REFERENCE && + indicateurValeur.dateValeur > this.SNBC_DATE_REFERENCE && (!dateApres2015 || - (dateApres2015 && indicateurValeur.date_valeur < dateApres2015)) + (dateApres2015 && indicateurValeur.dateValeur < dateApres2015)) ) { - dateApres2015 = indicateurValeur.date_valeur; + dateApres2015 = indicateurValeur.dateValeur; valeurApres2015 = indicateurValeur.resultat; } }); @@ -508,11 +503,11 @@ export default class TrajectoiresDataService { } verificationDonneesARemplirSuffisantes( - donnees: DonneesCalculTrajectoireARemplirType + donnees: DonneesCalculTrajectoireARemplirType, ): boolean { const { emissions_ges, consommations_finales } = donnees; const valeurEmissionGesValides = emissions_ges.valeurs.filter( - (v) => v.valeur !== null + (v) => v.valeur !== null, ).length; const valeurConsommationFinalesValides = consommations_finales.valeurs.filter((v) => v.valeur !== null).length; @@ -531,13 +526,13 @@ export default class TrajectoiresDataService { request: VerificationTrajectoireRequestType, tokenInfo: SupabaseJwtPayload, epci?: EpciType, - force_recuperation_donnees = false + forceRecuperationDonnees = false, ): Promise { // Vérification des droits await this.authService.verifieAccesAuxCollectivites( tokenInfo, [request.collectivite_id], - NiveauAcces.EDITION + NiveauAcces.EDITION, ); const response: VerificationDonneesSNBCResult = { @@ -545,13 +540,13 @@ export default class TrajectoiresDataService { }; if (request.force_recuperation_donnees) { - force_recuperation_donnees = true; + forceRecuperationDonnees = true; } if (!epci) { // Vérifie si la collectivité est une commune : const collectivite = await this.collectivitesService.getCollectivite( - request.collectivite_id + request.collectivite_id, ); if (collectivite.commune || !collectivite.epci) { response.status = VerificationDonneesSNBCStatus.COMMUNE_NON_SUPPORTEE; @@ -574,44 +569,44 @@ export default class TrajectoiresDataService { // sinon, vérifie s'il existe déjà des données trajectoire SNBC calculées : const valeurs = await this.indicateursService.getIndicateursValeurs({ - collectivite_id: request.collectivite_id, + collectiviteId: request.collectivite_id, sources: [this.SNBC_SOURCE.id], }); if (valeurs.length > 0) { response.valeurs = valeurs.map((v) => v.indicateur_valeur); // Si jamais les données on déjà été calculées, on récupère la source depuis le commentaire // un peu un hack mais le plus simple aujourd'hui - const premierCommentaire = response.valeurs[0].objectif_commentaire; + const premierCommentaire = response.valeurs[0].objectifCommentaire; const sourceIdentifiantManquants = this.extractSourceIdentifiantManquantsFromCommentaire( - premierCommentaire || '' + premierCommentaire || '', ); response.source_donnees_entree = sourceIdentifiantManquants?.source || ''; this.logger.log( - `Source des données SNBC déjà calculées : ${response.source_donnees_entree}` + `Source des données SNBC déjà calculées : ${response.source_donnees_entree}`, ); response.indentifiants_referentiel_manquants_donnees_entree = sourceIdentifiantManquants?.identifiants_referentiel_manquants || []; response.status = VerificationDonneesSNBCStatus.DEJA_CALCULE; - if (!force_recuperation_donnees) { + if (!forceRecuperationDonnees) { return response; } } // sinon, vérifie s'il y a les données suffisantes pour lancer le calcul : - // Si jamais les données ont déjà été calculées et que l'on a pas défini le flag force_utilisation_donnees_collectivite, on utilise la meme source + // Si jamais les données ont déjà été calculées et que l'on a pas défini le flag forceUtilisationDonneesCollectivite, on utilise la meme source const donneesCalculTrajectoireARemplir = await this.getValeursPourCalculTrajectoire( request.collectivite_id, !isNil(request.force_utilisation_donnees_collectivite) ? request.force_utilisation_donnees_collectivite : response.source_donnees_entree === - this.indicateursService.NULL_SOURCE_ID - ? true - : false + this.indicateursService.NULL_SOURCE_ID + ? true + : false, ); const donneesSuffisantes = this.verificationDonneesARemplirSuffisantes( - donneesCalculTrajectoireARemplir + donneesCalculTrajectoireARemplir, ); response.donnees_entree = donneesCalculTrajectoireARemplir; // si oui, retourne 'pret a calculer' @@ -629,13 +624,13 @@ export default class TrajectoiresDataService { async deleteTrajectoireSnbc( collectiviteId: number, snbcMetadonneesId?: number, - tokenInfo?: SupabaseJwtPayload + tokenInfo?: SupabaseJwtPayload, ): Promise { if (!snbcMetadonneesId) { const indicateurSourceMetadonnee = await this.indicateurSourcesService.getIndicateurSourceMetadonnee( this.SNBC_SOURCE.id, - this.SNBC_SOURCE_METADONNEES.date_version + this.SNBC_SOURCE_METADONNEES.dateVersion, ); if (indicateurSourceMetadonnee) { snbcMetadonneesId = indicateurSourceMetadonnee.id; @@ -644,7 +639,7 @@ export default class TrajectoiresDataService { if (!snbcMetadonneesId) { throw new InternalServerErrorException( - `Impossible de trouver l'identifiant de la metadonnée SNBC` + `Impossible de trouver l'identifiant de la metadonnée SNBC`, ); } @@ -653,13 +648,13 @@ export default class TrajectoiresDataService { await this.authService.verifieAccesAuxCollectivites( tokenInfo, [collectiviteId], - NiveauAcces.EDITION + NiveauAcces.EDITION, ); } await this.indicateursService.deleteIndicateurValeurs({ - collectivite_id: collectiviteId, - metadonnee_id: snbcMetadonneesId, + collectiviteId: collectiviteId, + metadonneeId: snbcMetadonneesId, }); } } diff --git a/backend/src/indicateurs/services/trajectoires-spreadsheet.service.ts b/backend/src/indicateurs/services/trajectoires-spreadsheet.service.ts index 1258e92e92..ca7199f32b 100644 --- a/backend/src/indicateurs/services/trajectoires-spreadsheet.service.ts +++ b/backend/src/indicateurs/services/trajectoires-spreadsheet.service.ts @@ -7,8 +7,8 @@ import { import { isNil, partition } from 'es-toolkit'; import * as _ from 'lodash'; import slugify from 'slugify'; -import { SupabaseJwtPayload } from '../../auth/models/auth.models'; -import { EpciType } from '../../collectivites/models/collectivite.models'; +import { SupabaseJwtPayload } from '../../auth/models/supabase-jwt.models'; +import { EpciType } from '../../collectivites/models/epci.table'; import GroupementsService from '../../collectivites/services/groupements.service'; import { BackendConfigurationType } from '../../config/configuration.model'; import ConfigurationService from '../../config/configuration.service'; @@ -21,10 +21,8 @@ import { DonneesCalculTrajectoireARemplirType, VerificationDonneesSNBCStatus, } from '../models/calcultrajectoire.models'; -import { - CreateIndicateurValeurType, - IndicateurDefinitionType, -} from '../models/indicateur.models'; +import { CreateIndicateurValeurType } from '../models/indicateur-valeur.table'; +import { IndicateurDefinitionType } from '../models/indicateur-definition.table'; import IndicateursService from './indicateurs.service'; import IndicateurSourcesService from './indicateurSources.service'; import TrajectoiresDataService from './trajectoires-data.service'; @@ -131,8 +129,8 @@ export default class TrajectoiresSpreadsheetService { ] = partition( indicateurDefinitions, (definition) => - definition.identifiant_referentiel?.startsWith( - this.trajectoiresDataService.CONSOMMATIONS_IDENTIFIANTS_PREFIX + definition.identifiantReferentiel?.startsWith( + this.trajectoiresDataService.CONSOMMATIONS_IDENTIFIANTS_PREFIX, ) || false ); @@ -142,8 +140,8 @@ export default class TrajectoiresSpreadsheetService { ] = partition( indicateurEmissionsSequestrationDefinitions, (definition) => - definition.identifiant_referentiel?.startsWith( - this.trajectoiresDataService.SEQUESTRATION_IDENTIFIANTS_PREFIX + definition.identifiantReferentiel?.startsWith( + this.trajectoiresDataService.SEQUESTRATION_IDENTIFIANTS_PREFIX, ) || false ); @@ -341,8 +339,8 @@ export default class TrajectoiresSpreadsheetService { ] = partition( indicateurResultatDefinitions, (definition) => - definition.identifiant_referentiel?.startsWith( - this.trajectoiresDataService.CONSOMMATIONS_IDENTIFIANTS_PREFIX + definition.identifiantReferentiel?.startsWith( + this.trajectoiresDataService.CONSOMMATIONS_IDENTIFIANTS_PREFIX, ) || false ); @@ -352,8 +350,8 @@ export default class TrajectoiresSpreadsheetService { ] = partition( indicateurResultatSequestrationEmissionsDefinitions, (definition) => - definition.identifiant_referentiel?.startsWith( - this.trajectoiresDataService.SEQUESTRATION_IDENTIFIANTS_PREFIX + definition.identifiantReferentiel?.startsWith( + this.trajectoiresDataService.SEQUESTRATION_IDENTIFIANTS_PREFIX, ) || false ); @@ -406,7 +404,7 @@ export default class TrajectoiresSpreadsheetService { result.trajectoire.emissions_ges.forEach((emissionGes) => { if ( this.signeInversionSequestration( - emissionGes.definition.identifiant_referentiel + emissionGes.definition.identifiantReferentiel ) ) { emissionGes.valeurs.forEach((valeur) => { @@ -424,7 +422,7 @@ export default class TrajectoiresSpreadsheetService { result.trajectoire.sequestrations.forEach((sequestration) => { if ( this.signeInversionSequestration( - sequestration.definition.identifiant_referentiel + sequestration.definition.identifiantReferentiel ) ) { sequestration.valeurs.forEach((valeur) => { @@ -569,7 +567,7 @@ export default class TrajectoiresSpreadsheetService { const indicateurResultatDefinition = indicateurResultatDefinitions.find( (definition) => - definition.identifiant_referentiel === + definition.identifiantReferentiel === identifiantReferentielSortie ); if (indicateurResultatDefinition) { @@ -577,7 +575,7 @@ export default class TrajectoiresSpreadsheetService { const floatValeur = parseFloat(valeur); if (!isNaN(floatValeur)) { const emissionGesOuSequestration = - !indicateurResultatDefinition.identifiant_referentiel?.startsWith( + !indicateurResultatDefinition.identifiantReferentiel?.startsWith( this.trajectoiresDataService .CONSOMMATIONS_IDENTIFIANTS_PREFIX ); @@ -586,19 +584,19 @@ export default class TrajectoiresSpreadsheetService { let facteur = emissionGesOuSequestration ? 1000 : 1; const signeInversionSequestration = this.signeInversionSequestration( - indicateurResultatDefinition.identifiant_referentiel + indicateurResultatDefinition.identifiantReferentiel ); if (signeInversionSequestration) { // 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 * facteur; } const indicateurValeur: CreateIndicateurValeurType = { - indicateur_id: indicateurResultatDefinition.id, - collectivite_id: collectiviteId, - metadonnee_id: indicateurSourceMetadonneeId, - date_valeur: `${2015 + columnIndex}-01-01`, + indicateurId: indicateurResultatDefinition.id, + collectiviteId: collectiviteId, + metadonneeId: indicateurSourceMetadonneeId, + dateValeur: `${2015 + columnIndex}-01-01`, objectif: floatValeur * facteur, - objectif_commentaire: objectifCommentaire, + objectifCommentaire: objectifCommentaire, }; indicateurValeursResultat.push(indicateurValeur); } else { diff --git a/backend/src/indicateurs/services/trajectoires-xlsx.service.ts b/backend/src/indicateurs/services/trajectoires-xlsx.service.ts index 78f7d06425..56867720fd 100644 --- a/backend/src/indicateurs/services/trajectoires-xlsx.service.ts +++ b/backend/src/indicateurs/services/trajectoires-xlsx.service.ts @@ -5,9 +5,10 @@ import { UnprocessableEntityException, } from '@nestjs/common'; import { NextFunction, Response } from 'express'; +import { JSZipGeneratorOptions } from 'jszip'; import { default as XlsxTemplate } from 'xlsx-template'; -import { SupabaseJwtPayload } from '../../auth/models/auth.models'; -import { EpciType } from '../../collectivites/models/collectivite.models'; +import { SupabaseJwtPayload } from '../../auth/models/supabase-jwt.models'; +import { EpciType } from '../../collectivites/models/epci.table'; import { CollectiviteRequestType } from '../../collectivites/models/collectivite.request'; import BackendConfigurationService from '../../config/configuration.service'; import SheetService from '../../spreadsheets/services/sheet.service'; @@ -28,7 +29,7 @@ export default class TrajectoiresXlsxService { constructor( private readonly configService: BackendConfigurationService, private readonly sheetService: SheetService, - private readonly trajectoiresDataService: TrajectoiresDataService + private readonly trajectoiresDataService: TrajectoiresDataService, ) { this.initXlsxBuffers(); } @@ -44,18 +45,18 @@ export default class TrajectoiresXlsxService { async downloadModeleTrajectoireSnbc( request: ModeleTrajectoireTelechargementRequestType, res: Response, - next: NextFunction + next: NextFunction, ) { try { if (!this.getIdentifiantXlsxCalcul()) { throw new InternalServerErrorException( - "L'identifiant du Xlsx pour le calcul des trajectoires SNBC est manquant" + "L'identifiant du Xlsx pour le calcul des trajectoires SNBC est manquant", ); } await this.initXlsxBuffers(request.force_recuperation_xlsx); const nomFichier = await this.sheetService.getFileName( - this.getIdentifiantXlsxCalcul() + this.getIdentifiantXlsxCalcul(), ); // Set the output file name. @@ -72,10 +73,10 @@ export default class TrajectoiresXlsxService { async initXlsxBuffers(forceRecuperation?: boolean) { if (!this.xlsxModeleBuffer || forceRecuperation) { this.logger.log( - `Récupération des données du fichier Xlsx de calcul ${this.getIdentifiantXlsxCalcul()} (force: ${forceRecuperation})` + `Récupération des données du fichier Xlsx de calcul ${this.getIdentifiantXlsxCalcul()} (force: ${forceRecuperation})`, ); this.xlsxModeleBuffer = await this.sheetService.getFileData( - this.getIdentifiantXlsxCalcul() + this.getIdentifiantXlsxCalcul(), ); if (this.xlsxModeleBuffer) { @@ -84,7 +85,7 @@ export default class TrajectoiresXlsxService { this.xlsxVideBuffer = await this.generationXlsxDonneesSubstituees( nouveauBuffer, { siren: null }, - null + null, ); } else { // Null in test @@ -99,7 +100,7 @@ export default class TrajectoiresXlsxService { await this.initXlsxBuffers(); } else { this.logger.log( - `Utilisation du buffer du fichier Xlsx de calcul déjà chargé` + `Utilisation du buffer du fichier Xlsx de calcul déjà chargé`, ); } return Buffer.from(this.xlsxModeleBuffer!); @@ -114,7 +115,7 @@ export default class TrajectoiresXlsxService { siren: { siren: number | null; }, - valeurIndicateurs: DonneesCalculTrajectoireARemplirType | null + valeurIndicateurs: DonneesCalculTrajectoireARemplirType | null, ): Promise { // Utilisation de xlsx-template car: // https://github.com/SheetJS/sheetjs/issues/347: sheetjs does not keep style @@ -141,7 +142,7 @@ export default class TrajectoiresXlsxService { emissionGesSequestrationConsommationsSubstitionValeurs[ cleSubstitution ] = 0; - } + }, ); this.trajectoiresDataService.SNBC_SEQUESTRATION_IDENTIFIANTS_REFERENTIEL.forEach( (identifiants) => { @@ -149,7 +150,7 @@ export default class TrajectoiresXlsxService { emissionGesSequestrationConsommationsSubstitionValeurs[ cleSubstitution ] = 0; - } + }, ); this.trajectoiresDataService.SNBC_CONSOMMATIONS_IDENTIFIANTS_REFERENTIEL.forEach( (identifiants) => { @@ -157,32 +158,32 @@ export default class TrajectoiresXlsxService { emissionGesSequestrationConsommationsSubstitionValeurs[ cleSubstitution ] = 0; - } + }, ); valeurIndicateurs?.emissions_ges.valeurs.forEach((valeur) => { const cleSubstitution = this.getXlsxCleSubstitution( - valeur.identifiants_referentiel + valeur.identifiants_referentiel, ); emissionGesSequestrationConsommationsSubstitionValeurs[cleSubstitution] = (valeur.valeur || 0) / 1000; }); valeurIndicateurs?.sequestrations.valeurs.forEach((valeur) => { const cleSubstitution = this.getXlsxCleSubstitution( - valeur.identifiants_referentiel + valeur.identifiants_referentiel, ); emissionGesSequestrationConsommationsSubstitionValeurs[cleSubstitution] = ((valeur.valeur || 0) * -1) / 1000; }); valeurIndicateurs?.consommations_finales.valeurs.forEach((valeur) => { const cleSubstitution = this.getXlsxCleSubstitution( - valeur.identifiants_referentiel + valeur.identifiants_referentiel, ); emissionGesSequestrationConsommationsSubstitionValeurs[cleSubstitution] = valeur.valeur || 0; }); template.substitute( emissionsGesSequestrationConsommationsSheetName, - emissionGesSequestrationConsommationsSubstitionValeurs + emissionGesSequestrationConsommationsSubstitionValeurs, ); // TODO: type it @@ -205,12 +206,12 @@ export default class TrajectoiresXlsxService { request: CollectiviteRequestType, tokenInfo: SupabaseJwtPayload, res: Response, - next: NextFunction + next: NextFunction, ) { try { if (!this.getIdentifiantXlsxCalcul()) { throw new InternalServerErrorException( - "L'identifiant du Xlsx pour le calcul des trajectoires SNBC est manquant" + "L'identifiant du Xlsx pour le calcul des trajectoires SNBC est manquant", ); } @@ -219,7 +220,7 @@ export default class TrajectoiresXlsxService { request, tokenInfo, undefined, - true + true, ); if ( @@ -228,7 +229,7 @@ export default class TrajectoiresXlsxService { !resultatVerification.epci ) { throw new UnprocessableEntityException( - `Le calcul de trajectoire SNBC peut uniquement être effectué pour un EPCI.` + `Le calcul de trajectoire SNBC peut uniquement être effectué pour un EPCI.`, ); } else if ( resultatVerification.status === @@ -242,16 +243,14 @@ export default class TrajectoiresXlsxService { .identifiants_referentiel_manquants || []), ]; throw new UnprocessableEntityException( - `Les indicateurs suivants n'ont pas de valeur pour l'année 2015 ou avec une interpolation possible : ${identifiantsReferentielManquants.join( - ', ' - )}, impossible de calculer la trajectoire SNBC.` + `Les indicateurs suivants n'ont pas de valeur pour l'année 2015 ou avec une interpolation possible : ${identifiantsReferentielManquants.join(', ')}, impossible de calculer la trajectoire SNBC.`, ); } const epci = resultatVerification.epci; const nomFichier = this.getNomFichierTrajectoire(epci); this.logger.log( - `Récupération des données du fichier ${this.getIdentifiantXlsxCalcul()}` + `Récupération des données du fichier ${this.getIdentifiantXlsxCalcul()}`, ); const xlsxBuffer = await this.getXlsxModeleBuffer(); @@ -262,7 +261,7 @@ export default class TrajectoiresXlsxService { const generatedData = await this.generationXlsxDonneesSubstituees( xlsxBuffer, sirenData, - resultatVerification.donnees_entree + resultatVerification.donnees_entree, ); this.logger.log(`Renvoi du fichier Xlsx généré`); diff --git a/backend/test/indicateurs/test-data/trajectoire-snbc-calcul-retour.ts b/backend/test/indicateurs/test-data/trajectoire-snbc-calcul-retour.ts index 4e5597370a..119c9da4d2 100644 --- a/backend/test/indicateurs/test-data/trajectoire-snbc-calcul-retour.ts +++ b/backend/test/indicateurs/test-data/trajectoire-snbc-calcul-retour.ts @@ -23,194 +23,193 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 4, - identifiant_referentiel: 'cae_1.c', + identifiantReferentiel: 'cae_1.c', titre: 'Emissions de gaz à effet de serre - résidentiel', - titre_long: - 'Emissions de gaz à effet de serre du secteur résidentiel', + titreLong: 'Emissions de gaz à effet de serre du secteur résidentiel', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14749, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 513790, }, { id: 14750, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 527250, }, { id: 14751, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 526110, }, { id: 14752, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 520210, }, { id: 14753, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 515500, }, { id: 14754, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 510140, }, { id: 14755, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 488690, }, { id: 14756, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 466220, }, { id: 14757, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 443710, }, { id: 14758, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 420870, }, { id: 14759, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 398190, }, { id: 14760, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 381200, }, { id: 14761, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 364500, }, { id: 14762, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 347280, }, { id: 14763, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 329840, }, { id: 14764, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 311380, }, { id: 14765, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 302470, }, { id: 14766, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 292770, }, { id: 14767, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 281950, }, { id: 14768, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 270600, }, { id: 14769, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 258270, }, { id: 14770, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 245330, }, { id: 14771, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 231730, }, { id: 14772, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 218320, }, { id: 14773, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 204290, }, { id: 14774, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 189440, }, { id: 14775, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 174160, }, { id: 14776, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 158870, }, { id: 14777, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 143280, }, { id: 14778, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 127750, }, { id: 14779, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 112070, }, { id: 14780, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 96210, }, { id: 14781, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 80210, }, { id: 14782, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 64090, }, { id: 14783, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 47750, }, { id: 14784, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 31190, }, ], @@ -218,195 +217,195 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 5, - identifiant_referentiel: 'cae_1.ca', + identifiantReferentiel: 'cae_1.ca', titre: 'Emissions de gaz à effet de serre - résidentiel - Chauffage / Maisons individuelles', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Résidentiel - Chauffage / Maisons individuelles', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 13921, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 154100, }, { id: 13922, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 159400, }, { id: 13923, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 160300, }, { id: 13924, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 158200, }, { id: 13925, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 156500, }, { id: 13926, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 154600, }, { id: 13927, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 147700, }, { id: 13928, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 140600, }, { id: 13929, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 133400, }, { id: 13930, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 126000, }, { id: 13931, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 118300, }, { id: 13932, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 112200, }, { id: 13933, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 105900, }, { id: 13934, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 99500, }, { id: 13935, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 93000, }, { id: 13936, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 86500, }, { id: 13937, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 83500, }, { id: 13938, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 80400, }, { id: 13939, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 77300, }, { id: 13940, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 74200, }, { id: 13941, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 71100, }, { id: 13942, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 68000, }, { id: 13943, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 64700, }, { id: 13944, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 61300, }, { id: 13945, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 57700, }, { id: 13946, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 54200, }, { id: 13947, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 50500, }, { id: 13948, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 46700, }, { id: 13949, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 42700, }, { id: 13950, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 38500, }, { id: 13951, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 34100, }, { id: 13952, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 29600, }, { id: 13953, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 24900, }, { id: 13954, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 20000, }, { id: 13955, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 15000, }, { id: 13956, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 9900, }, ], @@ -414,195 +413,195 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 6, - identifiant_referentiel: 'cae_1.cb', + identifiantReferentiel: 'cae_1.cb', titre: 'Emissions de gaz à effet de serre - résidentiel - Chauffage / Logement collectif', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Résidentiel - Chauffage / Logement collectif', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 13957, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 301600, }, { id: 13958, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 308100, }, { id: 13959, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 305900, }, { id: 13960, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 302800, }, { id: 13961, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 300400, }, { id: 13962, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 297600, }, { id: 13963, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 285600, }, { id: 13964, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 272800, }, { id: 13965, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 260100, }, { id: 13966, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 247400, }, { id: 13967, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 235100, }, { id: 13968, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 226400, }, { id: 13969, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 218100, }, { id: 13970, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 209600, }, { id: 13971, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 200800, }, { id: 13972, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 191100, }, { id: 13973, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 188100, }, { id: 13974, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 184200, }, { id: 13975, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 179100, }, { id: 13976, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 173300, }, { id: 13977, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 166600, }, { id: 13978, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 159100, }, { id: 13979, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 151000, }, { id: 13980, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 143100, }, { id: 13981, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 134600, }, { id: 13982, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 125100, }, { id: 13983, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 115300, }, { id: 13984, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 105300, }, { id: 13985, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 95200, }, { id: 13986, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 85100, }, { id: 13987, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 74900, }, { id: 13988, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 64500, }, { id: 13989, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 54000, }, { id: 13990, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 43400, }, { id: 13991, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 32500, }, { id: 13992, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 21300, }, ], @@ -610,195 +609,195 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 7, - identifiant_referentiel: 'cae_1.cc', + identifiantReferentiel: 'cae_1.cc', titre: 'Emissions de gaz à effet de serre - résidentiel - Autres usages', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Résidentiel - Autres usages', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 13993, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 58000, }, { id: 13994, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 59800, }, { id: 13995, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 60000, }, { id: 13996, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 59200, }, { id: 13997, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 58600, }, { id: 13998, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 58000, }, { id: 13999, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 55400, }, { id: 14000, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 52800, }, { id: 14001, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 50200, }, { id: 14002, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 47500, }, { id: 14003, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 44700, }, { id: 14004, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 42600, }, { id: 14005, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 40400, }, { id: 14006, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 38200, }, { id: 14007, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 36000, }, { id: 14008, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 33700, }, { id: 14009, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 30900, }, { id: 14010, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 28200, }, { id: 14011, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 25500, }, { id: 14012, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 23000, }, { id: 14013, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 20600, }, { id: 14014, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 18300, }, { id: 14015, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 16000, }, { id: 14016, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 13900, }, { id: 14017, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 12000, }, { id: 14018, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 10100, }, { id: 14019, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 8400, }, { id: 14020, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 6900, }, { id: 14021, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 5400, }, { id: 14022, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 4200, }, { id: 14023, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 3100, }, { id: 14024, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 2100, }, { id: 14025, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 1300, }, { id: 14026, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 700, }, { id: 14027, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 300, }, { id: 14028, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 0, }, ], @@ -806,193 +805,193 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 9, - identifiant_referentiel: 'cae_1.d', + identifiantReferentiel: 'cae_1.d', titre: 'Emissions de gaz à effet de serre - tertiaire', - titre_long: 'Emissions de gaz à effet de serre du secteur tertiaire', + titreLong: 'Emissions de gaz à effet de serre du secteur tertiaire', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14785, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 451040, }, { id: 14786, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 423080, }, { id: 14787, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 419680, }, { id: 14788, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 410230, }, { id: 14789, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 401770, }, { id: 14790, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 393000, }, { id: 14791, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 368050, }, { id: 14792, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 343330, }, { id: 14793, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 319230, }, { id: 14794, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 295580, }, { id: 14795, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 272470, }, { id: 14796, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 253530, }, { id: 14797, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 235240, }, { id: 14798, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 217200, }, { id: 14799, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 199780, }, { id: 14800, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 182650, }, { id: 14801, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 169050, }, { id: 14802, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 155970, }, { id: 14803, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 143260, }, { id: 14804, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 131200, }, { id: 14805, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 119520, }, { id: 14806, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 108360, }, { id: 14807, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 97660, }, { id: 14808, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 87550, }, { id: 14809, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 77880, }, { id: 14810, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 68750, }, { id: 14811, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 60090, }, { id: 14812, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 52000, }, { id: 14813, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 44400, }, { id: 14814, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 37330, }, { id: 14815, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 30780, }, { id: 14816, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 24760, }, { id: 14817, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 19240, }, { id: 14818, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 14250, }, { id: 14819, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 9800, }, { id: 14820, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 5870, }, ], @@ -1000,194 +999,194 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 10, - identifiant_referentiel: 'cae_1.da', + identifiantReferentiel: 'cae_1.da', titre: 'Emissions de gaz à effet de serre - tertiaire - Chauffage', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Tertiaire - Chauffage', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14029, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 391500, }, { id: 14030, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 367200, }, { id: 14031, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 364300, }, { id: 14032, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 356100, }, { id: 14033, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 348700, }, { id: 14034, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 341100, }, { id: 14035, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 319500, }, { id: 14036, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 298000, }, { id: 14037, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 277100, }, { id: 14038, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 256600, }, { id: 14039, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 236500, }, { id: 14040, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 220100, }, { id: 14041, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 204200, }, { id: 14042, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 188500, }, { id: 14043, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 173400, }, { id: 14044, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 158500, }, { id: 14045, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 147900, }, { id: 14046, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 137500, }, { id: 14047, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 127200, }, { id: 14048, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 117400, }, { id: 14049, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 107800, }, { id: 14050, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 98400, }, { id: 14051, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 89300, }, { id: 14052, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 80700, }, { id: 14053, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 72300, }, { id: 14054, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 64300, }, { id: 14055, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 56600, }, { id: 14056, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 49300, }, { id: 14057, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 42400, }, { id: 14058, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 35900, }, { id: 14059, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 29800, }, { id: 14060, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 24100, }, { id: 14061, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 18900, }, { id: 14062, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 14100, }, { id: 14063, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 9700, }, { id: 14064, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 5900, }, ], @@ -1195,195 +1194,195 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 11, - identifiant_referentiel: 'cae_1.db', + identifiantReferentiel: 'cae_1.db', titre: 'Emissions de gaz à effet de serre - tertiaire - Autres usages', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Tertiaire - Autres usages', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14065, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 59500, }, { id: 14066, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 55900, }, { id: 14067, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 55400, }, { id: 14068, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 54200, }, { id: 14069, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 53000, }, { id: 14070, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 51900, }, { id: 14071, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 48600, }, { id: 14072, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 45300, }, { id: 14073, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 42100, }, { id: 14074, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 39000, }, { id: 14075, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 36000, }, { id: 14076, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 33500, }, { id: 14077, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 31100, }, { id: 14078, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 28700, }, { id: 14079, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 26400, }, { id: 14080, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 24100, }, { id: 14081, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 21200, }, { id: 14082, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 18500, }, { id: 14083, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 16000, }, { id: 14084, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 13800, }, { id: 14085, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 11800, }, { id: 14086, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 9900, }, { id: 14087, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 8300, }, { id: 14088, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 6900, }, { id: 14089, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 5600, }, { id: 14090, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 4500, }, { id: 14091, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 3500, }, { id: 14092, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 2700, }, { id: 14093, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 2000, }, { id: 14094, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 1500, }, { id: 14095, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 1000, }, { id: 14096, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 600, }, { id: 14097, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 400, }, { id: 14098, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 200, }, { id: 14099, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 100, }, { id: 14100, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 0, }, ], @@ -1391,195 +1390,195 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 13, - identifiant_referentiel: 'cae_1.ea', + identifiantReferentiel: 'cae_1.ea', titre: 'Emissions de gaz à effet de serre - Transport routier - mobilité locale', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Transport routier - mobilité locale', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14461, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 228600, }, { id: 14462, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 229300, }, { id: 14463, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 226500, }, { id: 14464, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 223700, }, { id: 14465, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 221300, }, { id: 14466, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 218800, }, { id: 14467, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 213700, }, { id: 14468, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 208500, }, { id: 14469, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 203300, }, { id: 14470, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 198100, }, { id: 14471, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 192800, }, { id: 14472, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 187000, }, { id: 14473, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 181200, }, { id: 14474, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 175400, }, { id: 14475, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 169600, }, { id: 14476, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 163700, }, { id: 14477, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 155800, }, { id: 14478, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 147900, }, { id: 14479, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 139900, }, { id: 14480, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 132000, }, { id: 14481, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 123900, }, { id: 14482, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 115900, }, { id: 14483, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 107700, }, { id: 14484, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 99700, }, { id: 14485, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 91500, }, { id: 14486, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 83400, }, { id: 14487, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 75200, }, { id: 14488, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 67000, }, { id: 14489, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 58800, }, { id: 14490, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 50600, }, { id: 14491, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 42400, }, { id: 14492, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 34100, }, { id: 14493, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 25900, }, { id: 14494, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 17700, }, { id: 14495, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 9400, }, { id: 14496, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 1200, }, ], @@ -1587,195 +1586,195 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 14, - identifiant_referentiel: 'cae_1.eb', + identifiantReferentiel: 'cae_1.eb', titre: 'Emissions de gaz à effet de serre - Transport routier - autre', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Transport routier - autre', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14497, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 425000, }, { id: 14498, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 426400, }, { id: 14499, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 421100, }, { id: 14500, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 415800, }, { id: 14501, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 410500, }, { id: 14502, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 405200, }, { id: 14503, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 394900, }, { id: 14504, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 384600, }, { id: 14505, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 374200, }, { id: 14506, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 363900, }, { id: 14507, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 353500, }, { id: 14508, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 342400, }, { id: 14509, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 331200, }, { id: 14510, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 320100, }, { id: 14511, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 308900, }, { id: 14512, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 297800, }, { id: 14513, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 283000, }, { id: 14514, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 268200, }, { id: 14515, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 253400, }, { id: 14516, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 238600, }, { id: 14517, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 223800, }, { id: 14518, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 209100, }, { id: 14519, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 194300, }, { id: 14520, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 179500, }, { id: 14521, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 164700, }, { id: 14522, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 149900, }, { id: 14523, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 135200, }, { id: 14524, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 120400, }, { id: 14525, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 105600, }, { id: 14526, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 90800, }, { id: 14527, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 76000, }, { id: 14528, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 61300, }, { id: 14529, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 46500, }, { id: 14530, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 31700, }, { id: 14531, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 16900, }, { id: 14532, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 2100, }, ], @@ -1783,194 +1782,194 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 15, - identifiant_referentiel: 'cae_1.f', + identifiantReferentiel: 'cae_1.f', titre: 'Emissions de gaz à effet de serre - "autres transports"', - titre_long: + titreLong: 'Emissions de gaz à effet de serre du secteur des autres transport (hors routier)', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14533, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 21500, }, { id: 14534, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 18500, }, { id: 14535, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 19900, }, { id: 14536, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 21400, }, { id: 14537, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 22800, }, { id: 14538, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 24200, }, { id: 14539, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 23900, }, { id: 14540, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 23500, }, { id: 14541, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 23100, }, { id: 14542, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 22600, }, { id: 14543, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 22200, }, { id: 14544, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 22100, }, { id: 14545, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 22000, }, { id: 14546, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 22000, }, { id: 14547, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 21900, }, { id: 14548, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 21800, }, { id: 14549, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 19700, }, { id: 14550, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 17700, }, { id: 14551, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 15800, }, { id: 14552, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 14100, }, { id: 14553, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 12500, }, { id: 14554, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 11000, }, { id: 14555, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 9700, }, { id: 14556, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 8500, }, { id: 14557, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 7500, }, { id: 14558, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 6600, }, { id: 14559, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 5800, }, { id: 14560, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 5200, }, { id: 14561, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 4700, }, { id: 14562, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 4400, }, { id: 14563, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 4100, }, { id: 14564, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 4100, }, { id: 14565, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 4100, }, { id: 14566, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 4400, }, { id: 14567, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 4700, }, { id: 14568, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 5200, }, ], @@ -1978,194 +1977,194 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 16, - identifiant_referentiel: 'cae_1.g', + identifiantReferentiel: 'cae_1.g', titre: 'Emissions de gaz à effet de serre - agriculture', - titre_long: + titreLong: "Emissions de gaz à effet de serre du secteur de l'agriculture", description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14857, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 35300, }, { id: 14858, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 34910, }, { id: 14859, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 34500, }, { id: 14860, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 34100, }, { id: 14861, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 33690, }, { id: 14862, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 33280, }, { id: 14863, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 32780, }, { id: 14864, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 32280, }, { id: 14865, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 31780, }, { id: 14866, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 31280, }, { id: 14867, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 30780, }, { id: 14868, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 30400, }, { id: 14869, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 30020, }, { id: 14870, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 29640, }, { id: 14871, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 29260, }, { id: 14872, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 28880, }, { id: 14873, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 28290, }, { id: 14874, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 27710, }, { id: 14875, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 27120, }, { id: 14876, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 26530, }, { id: 14877, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 25940, }, { id: 14878, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 25350, }, { id: 14879, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 24760, }, { id: 14880, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 24170, }, { id: 14881, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 23580, }, { id: 14882, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 22990, }, { id: 14883, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 22400, }, { id: 14884, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 21800, }, { id: 14885, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 21210, }, { id: 14886, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 20610, }, { id: 14887, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 20020, }, { id: 14888, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 19460, }, { id: 14889, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 18900, }, { id: 14890, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 18350, }, { id: 14891, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 17790, }, { id: 14892, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 17240, }, ], @@ -2173,194 +2172,194 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 17, - identifiant_referentiel: 'cae_1.ga', + identifiantReferentiel: 'cae_1.ga', titre: 'Emissions de gaz à effet de serre - agriculture - Energie', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Agriculture - Energie', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14353, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 5400, }, { id: 14354, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 5200, }, { id: 14355, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 5100, }, { id: 14356, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 5000, }, { id: 14357, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 4900, }, { id: 14358, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 4700, }, { id: 14359, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 4600, }, { id: 14360, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 4500, }, { id: 14361, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 4400, }, { id: 14362, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 4300, }, { id: 14363, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 4200, }, { id: 14364, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 4100, }, { id: 14365, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 4000, }, { id: 14366, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 3900, }, { id: 14367, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 3900, }, { id: 14368, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 3800, }, { id: 14369, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 3600, }, { id: 14370, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 3500, }, { id: 14371, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 3300, }, { id: 14372, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 3200, }, { id: 14373, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 3000, }, { id: 14374, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 2900, }, { id: 14375, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 2700, }, { id: 14376, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 2500, }, { id: 14377, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 2400, }, { id: 14378, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 2200, }, { id: 14379, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 2100, }, { id: 14380, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 2000, }, { id: 14381, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 1800, }, { id: 14382, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 1700, }, { id: 14383, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 1600, }, { id: 14384, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 1400, }, { id: 14385, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 1200, }, { id: 14386, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 1000, }, { id: 14387, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 800, }, { id: 14388, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 600, }, ], @@ -2368,194 +2367,194 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 18, - identifiant_referentiel: 'cae_1.gb', + identifiantReferentiel: 'cae_1.gb', titre: 'Emissions de gaz à effet de serre - agriculture - Elevage', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Agriculture - Elevage', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14389, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 5400, }, { id: 14390, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 5300, }, { id: 14391, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 5300, }, { id: 14392, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 5200, }, { id: 14393, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 5100, }, { id: 14394, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 5100, }, { id: 14395, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 5000, }, { id: 14396, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 4900, }, { id: 14397, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 4900, }, { id: 14398, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 4800, }, { id: 14399, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 4700, }, { id: 14400, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 4700, }, { id: 14401, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 4600, }, { id: 14402, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 4600, }, { id: 14403, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 4500, }, { id: 14404, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 4500, }, { id: 14405, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 4400, }, { id: 14406, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 4400, }, { id: 14407, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 4300, }, { id: 14408, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 4300, }, { id: 14409, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 4200, }, { id: 14410, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 4200, }, { id: 14411, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 4100, }, { id: 14412, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 4100, }, { id: 14413, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 4100, }, { id: 14414, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 4000, }, { id: 14415, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 4000, }, { id: 14416, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 3900, }, { id: 14417, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 3900, }, { id: 14418, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 3800, }, { id: 14419, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 3800, }, { id: 14420, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 3700, }, { id: 14421, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 3700, }, { id: 14422, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 3600, }, { id: 14423, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 3600, }, { id: 14424, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 3600, }, ], @@ -2563,195 +2562,195 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 19, - identifiant_referentiel: 'cae_1.gc', + identifiantReferentiel: 'cae_1.gc', titre: 'Emissions de gaz à effet de serre - agriculture - Pratiques culturales', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Agriculture - Pratiques culturales', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14425, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 24500, }, { id: 14426, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 24300, }, { id: 14427, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 24100, }, { id: 14428, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 23900, }, { id: 14429, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 23700, }, { id: 14430, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 23500, }, { id: 14431, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 23100, }, { id: 14432, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 22800, }, { id: 14433, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 22500, }, { id: 14434, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 22200, }, { id: 14435, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 21800, }, { id: 14436, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 21600, }, { id: 14437, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 21400, }, { id: 14438, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 21100, }, { id: 14439, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 20900, }, { id: 14440, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 20600, }, { id: 14441, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 20300, }, { id: 14442, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 19900, }, { id: 14443, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 19500, }, { id: 14444, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 19100, }, { id: 14445, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 18700, }, { id: 14446, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 18300, }, { id: 14447, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 17900, }, { id: 14448, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 17500, }, { id: 14449, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 17100, }, { id: 14450, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 16800, }, { id: 14451, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 16300, }, { id: 14452, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 15900, }, { id: 14453, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 15500, }, { id: 14454, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 15100, }, { id: 14455, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 14600, }, { id: 14456, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 14300, }, { id: 14457, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 14000, }, { id: 14458, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 13700, }, { id: 14459, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 13400, }, { id: 14460, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 13100, }, ], @@ -2759,194 +2758,193 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 20, - identifiant_referentiel: 'cae_1.h', + identifiantReferentiel: 'cae_1.h', titre: 'Emissions de gaz à effet de serre - déchets', - titre_long: - 'Emissions de gaz à effet de serre du secteur des déchets', + titreLong: 'Emissions de gaz à effet de serre du secteur des déchets', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14929, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 39790, }, { id: 14930, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 38210, }, { id: 14931, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 36900, }, { id: 14932, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 35580, }, { id: 14933, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 34340, }, { id: 14934, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 33070, }, { id: 14935, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 32180, }, { id: 14936, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 31280, }, { id: 14937, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 30370, }, { id: 14938, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 29460, }, { id: 14939, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 28550, }, { id: 14940, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 27930, }, { id: 14941, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 27330, }, { id: 14942, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 26710, }, { id: 14943, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 26110, }, { id: 14944, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 25500, }, { id: 14945, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 24930, }, { id: 14946, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 24370, }, { id: 14947, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 23790, }, { id: 14948, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 23230, }, { id: 14949, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 22650, }, { id: 14950, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 22070, }, { id: 14951, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 21480, }, { id: 14952, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 20910, }, { id: 14953, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 20330, }, { id: 14954, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 19740, }, { id: 14955, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 19150, }, { id: 14956, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 18570, }, { id: 14957, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 17980, }, { id: 14958, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 17390, }, { id: 14959, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 16800, }, { id: 14960, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 16220, }, { id: 14961, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 15620, }, { id: 14962, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 15030, }, { id: 14963, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 14430, }, { id: 14964, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 13840, }, ], @@ -2954,195 +2952,195 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 21, - identifiant_referentiel: 'cae_1.i', + identifiantReferentiel: 'cae_1.i', titre: 'Emissions de gaz à effet de serre - industrie hors branche énergie', - titre_long: + titreLong: "Emissions de gaz à effet de serre du secteur de l'industrie hors branche énergie", description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14821, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 348530, }, { id: 14822, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 345350, }, { id: 14823, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 342380, }, { id: 14824, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 334960, }, { id: 14825, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 327540, }, { id: 14826, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 320110, }, { id: 14827, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 310780, }, { id: 14828, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 301460, }, { id: 14829, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 292170, }, { id: 14830, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 282900, }, { id: 14831, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 273650, }, { id: 14832, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 263300, }, { id: 14833, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 252960, }, { id: 14834, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 242630, }, { id: 14835, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 232300, }, { id: 14836, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 221980, }, { id: 14837, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 213270, }, { id: 14838, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 204540, }, { id: 14839, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 195810, }, { id: 14840, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 187050, }, { id: 14841, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 178280, }, { id: 14842, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 169500, }, { id: 14843, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 160710, }, { id: 14844, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 151890, }, { id: 14845, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 143070, }, { id: 14846, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 134230, }, { id: 14847, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 125380, }, { id: 14848, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 116510, }, { id: 14849, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 107630, }, { id: 14850, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 98740, }, { id: 14851, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 89830, }, { id: 14852, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 80910, }, { id: 14853, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 71980, }, { id: 14854, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 63030, }, { id: 14855, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 54070, }, { id: 14856, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 45100, }, ], @@ -3150,195 +3148,195 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 22, - identifiant_referentiel: 'cae_1.ia', + identifiantReferentiel: 'cae_1.ia', titre: 'Emissions de gaz à effet de serre - industrie - Métaux primaires', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Industrie - Métaux primaires', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14101, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 2700, }, { id: 14102, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 2600, }, { id: 14103, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 2600, }, { id: 14104, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 2500, }, { id: 14105, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 2500, }, { id: 14106, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 2400, }, { id: 14107, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 2400, }, { id: 14108, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 2300, }, { id: 14109, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 2300, }, { id: 14110, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 2200, }, { id: 14111, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 2200, }, { id: 14112, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 2100, }, { id: 14113, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 2100, }, { id: 14114, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 2000, }, { id: 14115, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 2000, }, { id: 14116, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 1900, }, { id: 14117, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 1800, }, { id: 14118, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 1800, }, { id: 14119, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 1700, }, { id: 14120, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 1700, }, { id: 14121, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 1600, }, { id: 14122, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 1600, }, { id: 14123, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 1500, }, { id: 14124, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 1500, }, { id: 14125, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 1400, }, { id: 14126, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 1400, }, { id: 14127, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 1300, }, { id: 14128, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 1200, }, { id: 14129, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 1200, }, { id: 14130, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 1100, }, { id: 14131, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 1100, }, { id: 14132, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 1000, }, { id: 14133, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 1000, }, { id: 14134, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 900, }, { id: 14135, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 900, }, { id: 14136, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 800, }, ], @@ -3346,194 +3344,194 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 23, - identifiant_referentiel: 'cae_1.ib', + identifiantReferentiel: 'cae_1.ib', titre: 'Emissions de gaz à effet de serre - industrie - Chimie', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Industrie - Chimie', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14137, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 160900, }, { id: 14138, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 157500, }, { id: 14139, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 154100, }, { id: 14140, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 150700, }, { id: 14141, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 147400, }, { id: 14142, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 144000, }, { id: 14143, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 140600, }, { id: 14144, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 137200, }, { id: 14145, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 133800, }, { id: 14146, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 130500, }, { id: 14147, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 127100, }, { id: 14148, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 123700, }, { id: 14149, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 120300, }, { id: 14150, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 117000, }, { id: 14151, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 113600, }, { id: 14152, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 110200, }, { id: 14153, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 105800, }, { id: 14154, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 101400, }, { id: 14155, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 97000, }, { id: 14156, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 92500, }, { id: 14157, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 88100, }, { id: 14158, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 83700, }, { id: 14159, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 79300, }, { id: 14160, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 74900, }, { id: 14161, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 70500, }, { id: 14162, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 66000, }, { id: 14163, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 61600, }, { id: 14164, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 57200, }, { id: 14165, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 52800, }, { id: 14166, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 48400, }, { id: 14167, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 44000, }, { id: 14168, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 39500, }, { id: 14169, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 35100, }, { id: 14170, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 30700, }, { id: 14171, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 26300, }, { id: 14172, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 21900, }, ], @@ -3541,195 +3539,195 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 24, - identifiant_referentiel: 'cae_1.ic', + identifiantReferentiel: 'cae_1.ic', titre: 'Emissions de gaz à effet de serre - industrie - Non-métalliques', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Industrie - Non-métalliques', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14173, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 30300, }, { id: 14174, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 29900, }, { id: 14175, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 29600, }, { id: 14176, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 29300, }, { id: 14177, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 28900, }, { id: 14178, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 28600, }, { id: 14179, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 28300, }, { id: 14180, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 27900, }, { id: 14181, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 27600, }, { id: 14182, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 27300, }, { id: 14183, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 26900, }, { id: 14184, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 26600, }, { id: 14185, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 26300, }, { id: 14186, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 25900, }, { id: 14187, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 25600, }, { id: 14188, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 25300, }, { id: 14189, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 24500, }, { id: 14190, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 23800, }, { id: 14191, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 23000, }, { id: 14192, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 22300, }, { id: 14193, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 21500, }, { id: 14194, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 20800, }, { id: 14195, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 20000, }, { id: 14196, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 19300, }, { id: 14197, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 18500, }, { id: 14198, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 17800, }, { id: 14199, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 17000, }, { id: 14200, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 16300, }, { id: 14201, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 15500, }, { id: 14202, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 14800, }, { id: 14203, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 14000, }, { id: 14204, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 13300, }, { id: 14205, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 12500, }, { id: 14206, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 11800, }, { id: 14207, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 11000, }, { id: 14208, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 10300, }, ], @@ -3737,195 +3735,195 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 25, - identifiant_referentiel: 'cae_1.id', + identifiantReferentiel: 'cae_1.id', titre: 'Emissions de gaz à effet de serre - industrie - Agro-industries', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Industrie - Agro-industries', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14209, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 53100, }, { id: 14210, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 52400, }, { id: 14211, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 51600, }, { id: 14212, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 50800, }, { id: 14213, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 50100, }, { id: 14214, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 49300, }, { id: 14215, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 48600, }, { id: 14216, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 47800, }, { id: 14217, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 47000, }, { id: 14218, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 46300, }, { id: 14219, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 45500, }, { id: 14220, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 44800, }, { id: 14221, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 44000, }, { id: 14222, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 43200, }, { id: 14223, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 42500, }, { id: 14224, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 41700, }, { id: 14225, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 39900, }, { id: 14226, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 38000, }, { id: 14227, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 36200, }, { id: 14228, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 34400, }, { id: 14229, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 32500, }, { id: 14230, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 30700, }, { id: 14231, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 28900, }, { id: 14232, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 27000, }, { id: 14233, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 25200, }, { id: 14234, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 23300, }, { id: 14235, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 21500, }, { id: 14236, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 19700, }, { id: 14237, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 17800, }, { id: 14238, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 16000, }, { id: 14239, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 14200, }, { id: 14240, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 12300, }, { id: 14241, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 10500, }, { id: 14242, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 8700, }, { id: 14243, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 6800, }, { id: 14244, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 5000, }, ], @@ -3933,194 +3931,194 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 26, - identifiant_referentiel: 'cae_1.ie', + identifiantReferentiel: 'cae_1.ie', titre: 'Emissions de gaz à effet de serre - industrie - Equipements', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Industrie - Equipements', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14245, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 81700, }, { id: 14246, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 78300, }, { id: 14247, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 74900, }, { id: 14248, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 71500, }, { id: 14249, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 68100, }, { id: 14250, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 64700, }, { id: 14251, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 61400, }, { id: 14252, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 58000, }, { id: 14253, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 54600, }, { id: 14254, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 51200, }, { id: 14255, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 47800, }, { id: 14256, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 44500, }, { id: 14257, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 41100, }, { id: 14258, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 37700, }, { id: 14259, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 34300, }, { id: 14260, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 30900, }, { id: 14261, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 29700, }, { id: 14262, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 28500, }, { id: 14263, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 27400, }, { id: 14264, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 26200, }, { id: 14265, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 25000, }, { id: 14266, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 23800, }, { id: 14267, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 22600, }, { id: 14268, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 21400, }, { id: 14269, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 20200, }, { id: 14270, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 19000, }, { id: 14271, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 17800, }, { id: 14272, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 16700, }, { id: 14273, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 15500, }, { id: 14274, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 14300, }, { id: 14275, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 13100, }, { id: 14276, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 11900, }, { id: 14277, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 10700, }, { id: 14278, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 9500, }, { id: 14279, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 8300, }, { id: 14280, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 7100, }, ], @@ -4128,195 +4126,195 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 27, - identifiant_referentiel: 'cae_1.if', + identifiantReferentiel: 'cae_1.if', titre: 'Emissions de gaz à effet de serre - industrie - Papier-carton', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Industrie - Papier-carton', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14281, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 13300, }, { id: 14282, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 13000, }, { id: 14283, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 12700, }, { id: 14284, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 12300, }, { id: 14285, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 12000, }, { id: 14286, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 11700, }, { id: 14287, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 11300, }, { id: 14288, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 11000, }, { id: 14289, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 10700, }, { id: 14290, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 10300, }, { id: 14291, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 10000, }, { id: 14292, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 9700, }, { id: 14293, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 9300, }, { id: 14294, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 9000, }, { id: 14295, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 8700, }, { id: 14296, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 8300, }, { id: 14297, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 7900, }, { id: 14298, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 7500, }, { id: 14299, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 7100, }, { id: 14300, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 6700, }, { id: 14301, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 6200, }, { id: 14302, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 5800, }, { id: 14303, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 5400, }, { id: 14304, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 5000, }, { id: 14305, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 4600, }, { id: 14306, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 4200, }, { id: 14307, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 3700, }, { id: 14308, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 3300, }, { id: 14309, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 2900, }, { id: 14310, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 2500, }, { id: 14311, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 2100, }, { id: 14312, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 1700, }, { id: 14313, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 1200, }, { id: 14314, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 800, }, { id: 14315, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 400, }, { id: 14316, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 0, }, ], @@ -4324,195 +4322,195 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 28, - identifiant_referentiel: 'cae_1.ig', + identifiantReferentiel: 'cae_1.ig', titre: 'Emissions de gaz à effet de serre - industrie - Autres industries', - titre_long: + titreLong: 'Emissions de gaz à effet de serre secteur Industrie - Autres industries', description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14317, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 6600, }, { id: 14318, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 11700, }, { id: 14319, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 17000, }, { id: 14320, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 17800, }, { id: 14321, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 18600, }, { id: 14322, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 19400, }, { id: 14323, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 18300, }, { id: 14324, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 17200, }, { id: 14325, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 16200, }, { id: 14326, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 15100, }, { id: 14327, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 14100, }, { id: 14328, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 12000, }, { id: 14329, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 9900, }, { id: 14330, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 7800, }, { id: 14331, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 5700, }, { id: 14332, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 3700, }, { id: 14333, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 3600, }, { id: 14334, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 3500, }, { id: 14335, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 3500, }, { id: 14336, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 3400, }, { id: 14337, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 3300, }, { id: 14338, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 3100, }, { id: 14339, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 3000, }, { id: 14340, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 2900, }, { id: 14341, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 2700, }, { id: 14342, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 2500, }, { id: 14343, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 2300, }, { id: 14344, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 2100, }, { id: 14345, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 1900, }, { id: 14346, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 1700, }, { id: 14347, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 1400, }, { id: 14348, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 1200, }, { id: 14349, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 900, }, { id: 14350, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 600, }, { id: 14351, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 300, }, { id: 14352, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 0, }, ], @@ -4520,195 +4518,195 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 29, - identifiant_referentiel: 'cae_1.j', + identifiantReferentiel: 'cae_1.j', titre: "Emissions de gaz à effet de serre de l'industrie branche énergie", - titre_long: + titreLong: "Emissions de gaz à effet de serre du secteur de l'industrie branche énergie", description: '', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14965, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 0, }, { id: 14966, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 0, }, { id: 14967, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 0, }, { id: 14968, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 0, }, { id: 14969, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 0, }, { id: 14970, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 0, }, { id: 14971, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 0, }, { id: 14972, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 0, }, { id: 14973, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 0, }, { id: 14974, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 0, }, { id: 14975, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 0, }, { id: 14976, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 0, }, { id: 14977, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 0, }, { id: 14978, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 0, }, { id: 14979, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 0, }, { id: 14980, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 0, }, { id: 14981, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 0, }, { id: 14982, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 0, }, { id: 14983, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 0, }, { id: 14984, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 0, }, { id: 14985, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 0, }, { id: 14986, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 0, }, { id: 14987, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 0, }, { id: 14988, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 0, }, { id: 14989, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 0, }, { id: 14990, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 0, }, { id: 14991, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 0, }, { id: 14992, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 0, }, { id: 14993, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 0, }, { id: 14994, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 0, }, { id: 14995, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 0, }, { id: 14996, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 0, }, { id: 14997, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 0, }, { id: 14998, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 0, }, { id: 14999, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 0, }, { id: 15000, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 0, }, ], @@ -4716,194 +4714,194 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 30, - identifiant_referentiel: 'cae_1.k', + identifiantReferentiel: 'cae_1.k', titre: 'Emissions de gaz à effet de serre - Transports', - titre_long: 'Emissions de gaz à effet de serre secteur Transports', + titreLong: 'Emissions de gaz à effet de serre secteur Transports', description: '

Somme des transports routiers (cae_1.e) et autres transports (cae_1.f)

\n', unite: 'teq CO2', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14893, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 675090, }, { id: 14894, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 674220, }, { id: 14895, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 667520, }, { id: 14896, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 660820, }, { id: 14897, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 654620, }, { id: 14898, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 648230, }, { id: 14899, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 632470, }, { id: 14900, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 616510, }, { id: 14901, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 600580, }, { id: 14902, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 584570, }, { id: 14903, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 568530, }, { id: 14904, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 551430, }, { id: 14905, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 534490, }, { id: 14906, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 517390, }, { id: 14907, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 500430, }, { id: 14908, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 483320, }, { id: 14909, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 458500, }, { id: 14910, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 433810, }, { id: 14911, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 409120, }, { id: 14912, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 384680, }, { id: 14913, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 360250, }, { id: 14914, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 335960, }, { id: 14915, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 311720, }, { id: 14916, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 287700, }, { id: 14917, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 263720, }, { id: 14918, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 239900, }, { id: 14919, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 216130, }, { id: 14920, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 192570, }, { id: 14921, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 169090, }, { id: 14922, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 145750, }, { id: 14923, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 122550, }, { id: 14924, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 99480, }, { id: 14925, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 76520, }, { id: 14926, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 53700, }, { id: 14927, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 31030, }, { id: 14928, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 8500, }, ], @@ -4913,193 +4911,193 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 62, - identifiant_referentiel: 'cae_2.e', + identifiantReferentiel: 'cae_2.e', titre: 'Consommation énergétique - résidentiel', - titre_long: 'Consommation énergétique du résidentiel', + titreLong: 'Consommation énergétique du résidentiel', description: '', unite: 'GWh', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 15001, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 3609.24, }, { id: 15002, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 3581.17, }, { id: 15003, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 3552.22, }, { id: 15004, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 3537.29, }, { id: 15005, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 3530.92, }, { id: 15006, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 3520.98, }, { id: 15007, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 3458.54, }, { id: 15008, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 3392.33, }, { id: 15009, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 3328.51, }, { id: 15010, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 3265.17, }, { id: 15011, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 3205.59, }, { id: 15012, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 3146.12, }, { id: 15013, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 3092.07, }, { id: 15014, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 3037.47, }, { id: 15015, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 2985.65, }, { id: 15016, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 2930.33, }, { id: 15017, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 2918.85, }, { id: 15018, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 2904.25, }, { id: 15019, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 2883.16, }, { id: 15020, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 2861.4, }, { id: 15021, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 2834.02, }, { id: 15022, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 2804.27, }, { id: 15023, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 2771.16, }, { id: 15024, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 2742.56, }, { id: 15025, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 2710.49, }, { id: 15026, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 2673.86, }, { id: 15027, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 2634.41, }, { id: 15028, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 2597.76, }, { id: 15029, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 2559.11, }, { id: 15030, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 2523.36, }, { id: 15031, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 2488.28, }, { id: 15032, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 2453.23, }, { id: 15033, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 2418.26, }, { id: 15034, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 2385.04, }, { id: 15035, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 2351.75, }, { id: 15036, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 2319.05, }, ], @@ -5107,195 +5105,195 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 63, - identifiant_referentiel: 'cae_2.ea', + identifiantReferentiel: 'cae_2.ea', titre: 'Consommation énergétique - résidentiel - Chauffage / Maisons individuelles', - titre_long: + titreLong: 'Consommation énergétique secteur résidentiel - Chauffage / Maisons individuelles', description: '', unite: 'GWh', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14569, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 763.9, }, { id: 14570, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 765.5, }, { id: 14571, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 767.4, }, { id: 14572, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 765.9, }, { id: 14573, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 766.1, }, { id: 14574, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 765.7, }, { id: 14575, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 753.2, }, { id: 14576, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 740.3, }, { id: 14577, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 727.1, }, { id: 14578, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 713.3, }, { id: 14579, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 698.5, }, { id: 14580, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 682.3, }, { id: 14581, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 665.9, }, { id: 14582, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 648.4, }, { id: 14583, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 631.2, }, { id: 14584, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 613.7, }, { id: 14585, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 596.9, }, { id: 14586, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 581.2, }, { id: 14587, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 566, }, { id: 14588, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 552.3, }, { id: 14589, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 539, }, { id: 14590, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 526.5, }, { id: 14591, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 514.2, }, { id: 14592, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 502, }, { id: 14593, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 489.8, }, { id: 14594, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 479.2, }, { id: 14595, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 468.3, }, { id: 14596, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 458.1, }, { id: 14597, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 447.6, }, { id: 14598, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 436.7, }, { id: 14599, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 426, }, { id: 14600, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 415.3, }, { id: 14601, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 404, }, { id: 14602, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 392.6, }, { id: 14603, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 381.3, }, { id: 14604, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 370.2, }, ], @@ -5303,195 +5301,195 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 64, - identifiant_referentiel: 'cae_2.eb', + identifiantReferentiel: 'cae_2.eb', titre: 'Consommation énergétique - résidentiel - Chauffage / Logement collectif', - titre_long: + titreLong: 'Consommation énergétique secteur résidentiel - Chauffage / Logement collectif', description: '', unite: 'GWh', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14605, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 1494.7, }, { id: 14606, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 1480, }, { id: 14607, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 1464.2, }, { id: 14608, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 1465.6, }, { id: 14609, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 1470.9, }, { id: 14610, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 1474.3, }, { id: 14611, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 1456.6, }, { id: 14612, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 1436.3, }, { id: 14613, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 1418, }, { id: 14614, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 1400.8, }, { id: 14615, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 1388, }, { id: 14616, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 1377.5, }, { id: 14617, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 1371.2, }, { id: 14618, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 1366.1, }, { id: 14619, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 1362.2, }, { id: 14620, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 1355.6, }, { id: 14621, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 1345.4, }, { id: 14622, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 1331.4, }, { id: 14623, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 1311.7, }, { id: 14624, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 1289.4, }, { id: 14625, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 1262.4, }, { id: 14626, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 1232.8, }, { id: 14627, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 1200.7, }, { id: 14628, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 1172.6, }, { id: 14629, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 1142.6, }, { id: 14630, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 1106.6, }, { id: 14631, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 1069.6, }, { id: 14632, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 1034.2, }, { id: 14633, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 998.6, }, { id: 14634, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 966.5, }, { id: 14635, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 935.4, }, { id: 14636, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 905, }, { id: 14637, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 876.7, }, { id: 14638, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 850.7, }, { id: 14639, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 825.1, }, { id: 14640, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 800.2, }, ], @@ -5499,194 +5497,194 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 65, - identifiant_referentiel: 'cae_2.ec', + identifiantReferentiel: 'cae_2.ec', titre: 'Consommation énergétique - résidentiel - Autres usages', - titre_long: + titreLong: 'Consommation énergétique secteur résidentiel - Autres usages', description: '', unite: 'GWh', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14641, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 1350.6, }, { id: 14642, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 1335.6, }, { id: 14643, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 1320.7, }, { id: 14644, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 1305.8, }, { id: 14645, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 1294, }, { id: 14646, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 1281, }, { id: 14647, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 1248.7, }, { id: 14648, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 1215.8, }, { id: 14649, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 1183.4, }, { id: 14650, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 1151.1, }, { id: 14651, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 1119.1, }, { id: 14652, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 1086.4, }, { id: 14653, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 1055, }, { id: 14654, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 1023.1, }, { id: 14655, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 992.3, }, { id: 14656, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 961.1, }, { id: 14657, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 976.6, }, { id: 14658, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 991.7, }, { id: 14659, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 1005.5, }, { id: 14660, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 1019.7, }, { id: 14661, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 1032.6, }, { id: 14662, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 1045, }, { id: 14663, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 1056.3, }, { id: 14664, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 1067.9, }, { id: 14665, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 1078.1, }, { id: 14666, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 1088, }, { id: 14667, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 1096.5, }, { id: 14668, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 1105.5, }, { id: 14669, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 1113, }, { id: 14670, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 1120.2, }, { id: 14671, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 1126.9, }, { id: 14672, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 1133, }, { id: 14673, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 1137.6, }, { id: 14674, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 1141.8, }, { id: 14675, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 1145.3, }, { id: 14676, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 1148.6, }, ], @@ -5694,193 +5692,193 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 66, - identifiant_referentiel: 'cae_2.f', + identifiantReferentiel: 'cae_2.f', titre: 'Consommation énergétique - tertiaire', - titre_long: 'Consommation énergétique du tertiaire', + titreLong: 'Consommation énergétique du tertiaire', description: '', unite: 'GWh', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 15037, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 3198.84, }, { id: 15038, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 3177.51, }, { id: 15039, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 3156.22, }, { id: 15040, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 3134.95, }, { id: 15041, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 3120.82, }, { id: 15042, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 3103.89, }, { id: 15043, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 3054.93, }, { id: 15044, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 3003.59, }, { id: 15045, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 2953.13, }, { id: 15046, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 2901.89, }, { id: 15047, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 2850.72, }, { id: 15048, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 2797.11, }, { id: 15049, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 2745.94, }, { id: 15050, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 2692.62, }, { id: 15051, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 2641.48, }, { id: 15052, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 2588.46, }, { id: 15053, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 2557.93, }, { id: 15054, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 2527.8, }, { id: 15055, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 2495.38, }, { id: 15056, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 2465.51, }, { id: 15057, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 2433.48, }, { id: 15058, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 2401.58, }, { id: 15059, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 2368.34, }, { id: 15060, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 2337.11, }, { id: 15061, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 2303.9, }, { id: 15062, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 2271.39, }, { id: 15063, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 2236.83, }, { id: 15064, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 2204.57, }, { id: 15065, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 2170.48, }, { id: 15066, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 2136.82, }, { id: 15067, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 2103.36, }, { id: 15068, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 2069.77, }, { id: 15069, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 2034.52, }, { id: 15070, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 1999.68, }, { id: 15071, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 1964.73, }, { id: 15072, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 1930.28, }, ], @@ -5888,193 +5886,193 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 67, - identifiant_referentiel: 'cae_2.fa', + identifiantReferentiel: 'cae_2.fa', titre: 'Consommation énergétique - tertiaire - Chauffage', - titre_long: 'Consommation énergétique secteur tertiaire - Chauffage', + titreLong: 'Consommation énergétique secteur tertiaire - Chauffage', description: '', unite: 'GWh', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14677, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 1404.8, }, { id: 14678, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 1382.3, }, { id: 14679, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 1360.1, }, { id: 14680, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 1338, }, { id: 14681, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 1319.1, }, { id: 14682, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 1299.1, }, { id: 14683, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 1266, }, { id: 14684, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 1232.3, }, { id: 14685, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 1199.4, }, { id: 14686, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 1166.5, }, { id: 14687, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 1134.1, }, { id: 14688, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 1101.1, }, { id: 14689, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 1069.5, }, { id: 14690, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 1037.5, }, { id: 14691, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 1006.8, }, { id: 14692, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 975.8, }, { id: 14693, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 961.6, }, { id: 14694, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 947.6, }, { id: 14695, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 932.8, }, { id: 14696, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 919.1, }, { id: 14697, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 904.6, }, { id: 14698, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 890.2, }, { id: 14699, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 875.4, }, { id: 14700, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 861.4, }, { id: 14701, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 846.8, }, { id: 14702, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 832.4, }, { id: 14703, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 817.4, }, { id: 14704, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 803.3, }, { id: 14705, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 788.6, }, { id: 14706, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 774.1, }, { id: 14707, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 759.8, }, { id: 14708, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 745.5, }, { id: 14709, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 730.6, }, { id: 14710, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 716, }, { id: 14711, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 701.4, }, { id: 14712, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 687.1, }, ], @@ -6082,194 +6080,194 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 68, - identifiant_referentiel: 'cae_2.fb', + identifiantReferentiel: 'cae_2.fb', titre: 'Consommation énergétique - tertiaire - Autres usages', - titre_long: + titreLong: 'Consommation énergétique secteur tertiaire - Autres usages', description: '', unite: 'GWh', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 14713, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 1794.1, }, { id: 14714, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 1795.2, }, { id: 14715, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 1796.1, }, { id: 14716, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 1796.9, }, { id: 14717, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 1801.7, }, { id: 14718, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 1804.7, }, { id: 14719, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 1788.9, }, { id: 14720, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 1771.3, }, { id: 14721, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 1753.8, }, { id: 14722, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 1735.4, }, { id: 14723, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 1716.6, }, { id: 14724, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 1696, }, { id: 14725, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 1676.4, }, { id: 14726, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 1655.1, }, { id: 14727, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 1634.7, }, { id: 14728, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 1612.7, }, { id: 14729, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 1596.4, }, { id: 14730, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 1580.2, }, { id: 14731, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 1562.6, }, { id: 14732, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 1546.4, }, { id: 14733, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 1528.9, }, { id: 14734, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 1511.4, }, { id: 14735, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 1492.9, }, { id: 14736, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 1475.7, }, { id: 14737, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 1457.2, }, { id: 14738, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 1439, }, { id: 14739, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 1419.4, }, { id: 14740, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 1401.3, }, { id: 14741, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 1381.9, }, { id: 14742, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 1362.7, }, { id: 14743, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 1343.6, }, { id: 14744, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 1324.3, }, { id: 14745, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 1303.9, }, { id: 14746, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 1283.7, }, { id: 14747, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 1263.3, }, { id: 14748, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 1243.2, }, ], @@ -6277,193 +6275,193 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 71, - identifiant_referentiel: 'cae_2.i', + identifiantReferentiel: 'cae_2.i', titre: 'Consommation énergétique - agriculture', - titre_long: "Consommation énergétique de l'agriculture", + titreLong: "Consommation énergétique de l'agriculture", description: '', unite: 'GWh', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 15073, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 23.14, }, { id: 15074, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 22.98, }, { id: 15075, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 22.81, }, { id: 15076, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 22.65, }, { id: 15077, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 22.49, }, { id: 15078, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 22.32, }, { id: 15079, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 22.03, }, { id: 15080, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 21.73, }, { id: 15081, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 21.43, }, { id: 15082, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 21.14, }, { id: 15083, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 20.84, }, { id: 15084, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 20.68, }, { id: 15085, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 20.53, }, { id: 15086, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 20.37, }, { id: 15087, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 20.21, }, { id: 15088, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 20.06, }, { id: 15089, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 19.65, }, { id: 15090, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 19.23, }, { id: 15091, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 18.82, }, { id: 15092, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 18.41, }, { id: 15093, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 18, }, { id: 15094, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 17.59, }, { id: 15095, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 17.17, }, { id: 15096, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 16.76, }, { id: 15097, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 16.35, }, { id: 15098, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 15.94, }, { id: 15099, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 15.52, }, { id: 15100, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 15.11, }, { id: 15101, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 14.7, }, { id: 15102, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 14.29, }, { id: 15103, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 13.88, }, { id: 15104, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 13.46, }, { id: 15105, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 13.05, }, { id: 15106, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 12.64, }, { id: 15107, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 12.23, }, { id: 15108, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 11.81, }, ], @@ -6471,193 +6469,193 @@ export const trajectoireSnbcCalculRetour: CalculTrajectoireResponseType = { { definition: { id: 72, - identifiant_referentiel: 'cae_2.j', + identifiantReferentiel: 'cae_2.j', titre: 'Consommation énergétique - déchets', - titre_long: 'Consommation énergétique des déchets', + titreLong: 'Consommation énergétique des déchets', description: '', unite: 'GWh', - borne_min: null, - borne_max: null, + borneMin: null, + borneMax: null, }, valeurs: [ { id: 15109, - date_valeur: '2015-01-01', + dateValeur: '2015-01-01', objectif: 0, }, { id: 15110, - date_valeur: '2016-01-01', + dateValeur: '2016-01-01', objectif: 0, }, { id: 15111, - date_valeur: '2017-01-01', + dateValeur: '2017-01-01', objectif: 0, }, { id: 15112, - date_valeur: '2018-01-01', + dateValeur: '2018-01-01', objectif: 0, }, { id: 15113, - date_valeur: '2019-01-01', + dateValeur: '2019-01-01', objectif: 0, }, { id: 15114, - date_valeur: '2020-01-01', + dateValeur: '2020-01-01', objectif: 0, }, { id: 15115, - date_valeur: '2021-01-01', + dateValeur: '2021-01-01', objectif: 0, }, { id: 15116, - date_valeur: '2022-01-01', + dateValeur: '2022-01-01', objectif: 0, }, { id: 15117, - date_valeur: '2023-01-01', + dateValeur: '2023-01-01', objectif: 0, }, { id: 15118, - date_valeur: '2024-01-01', + dateValeur: '2024-01-01', objectif: 0, }, { id: 15119, - date_valeur: '2025-01-01', + dateValeur: '2025-01-01', objectif: 0, }, { id: 15120, - date_valeur: '2026-01-01', + dateValeur: '2026-01-01', objectif: 0, }, { id: 15121, - date_valeur: '2027-01-01', + dateValeur: '2027-01-01', objectif: 0, }, { id: 15122, - date_valeur: '2028-01-01', + dateValeur: '2028-01-01', objectif: 0, }, { id: 15123, - date_valeur: '2029-01-01', + dateValeur: '2029-01-01', objectif: 0, }, { id: 15124, - date_valeur: '2030-01-01', + dateValeur: '2030-01-01', objectif: 0, }, { id: 15125, - date_valeur: '2031-01-01', + dateValeur: '2031-01-01', objectif: 0, }, { id: 15126, - date_valeur: '2032-01-01', + dateValeur: '2032-01-01', objectif: 0, }, { id: 15127, - date_valeur: '2033-01-01', + dateValeur: '2033-01-01', objectif: 0, }, { id: 15128, - date_valeur: '2034-01-01', + dateValeur: '2034-01-01', objectif: 0, }, { id: 15129, - date_valeur: '2035-01-01', + dateValeur: '2035-01-01', objectif: 0, }, { id: 15130, - date_valeur: '2036-01-01', + dateValeur: '2036-01-01', objectif: 0, }, { id: 15131, - date_valeur: '2037-01-01', + dateValeur: '2037-01-01', objectif: 0, }, { id: 15132, - date_valeur: '2038-01-01', + dateValeur: '2038-01-01', objectif: 0, }, { id: 15133, - date_valeur: '2039-01-01', + dateValeur: '2039-01-01', objectif: 0, }, { id: 15134, - date_valeur: '2040-01-01', + dateValeur: '2040-01-01', objectif: 0, }, { id: 15135, - date_valeur: '2041-01-01', + dateValeur: '2041-01-01', objectif: 0, }, { id: 15136, - date_valeur: '2042-01-01', + dateValeur: '2042-01-01', objectif: 0, }, { id: 15137, - date_valeur: '2043-01-01', + dateValeur: '2043-01-01', objectif: 0, }, { id: 15138, - date_valeur: '2044-01-01', + dateValeur: '2044-01-01', objectif: 0, }, { id: 15139, - date_valeur: '2045-01-01', + dateValeur: '2045-01-01', objectif: 0, }, { id: 15140, - date_valeur: '2046-01-01', + dateValeur: '2046-01-01', objectif: 0, }, { id: 15141, - date_valeur: '2047-01-01', + dateValeur: '2047-01-01', objectif: 0, }, { id: 15142, - date_valeur: '2048-01-01', + dateValeur: '2048-01-01', objectif: 0, }, { id: 15143, - date_valeur: '2049-01-01', + dateValeur: '2049-01-01', objectif: 0, }, { id: 15144, - date_valeur: '2050-01-01', + dateValeur: '2050-01-01', objectif: 0, }, ], diff --git a/backend/test/indicateurs/trajectoire-snbc.e2e-spec.ts b/backend/test/indicateurs/trajectoire-snbc.e2e-spec.ts index c881365d3c..6da67e6b7a 100644 --- a/backend/test/indicateurs/trajectoire-snbc.e2e-spec.ts +++ b/backend/test/indicateurs/trajectoire-snbc.e2e-spec.ts @@ -87,7 +87,7 @@ describe('Calcul de trajectoire SNBC', () => { status: VerificationDonneesSNBCStatus.DONNEES_MANQUANTES, epci: { id: 19, - collectivite_id: 3829, + collectiviteId: 3829, nom: 'CA du Pays de Laon', siren: '200043495', nature: 'CA', @@ -307,7 +307,7 @@ describe('Calcul de trajectoire SNBC', () => { status: VerificationDonneesSNBCStatus.PRET_A_CALCULER, epci: { id: 1126, - collectivite_id: 4936, + collectiviteId: 4936, nom: 'Eurométropole de Strasbourg', siren: '246700488', nature: 'METRO', From f635d717b6f35e737754adefa3a6b64e55e0ad25 Mon Sep 17 00:00:00 2001 From: Amandine Date: Fri, 20 Sep 2024 11:18:35 +0200 Subject: [PATCH 18/22] =?UTF-8?q?Backend=20-=20Ajoute=20les=20utilisateurs?= =?UTF-8?q?=20et=20les=20droits=20supports=20et=20v=C3=A9rifi=C3=A9s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/auth/auth.module.ts | 2 + backend/src/auth/guards/auth.guard.ts | 2 +- backend/src/auth/models/auth-users.table.ts | 52 ++++++ backend/src/auth/models/dcp.table.ts | 22 +++ ....ts => private-utilisateur-droit.table.ts} | 34 +--- .../src/auth/models/supabase-jwt.models.ts | 18 ++ .../auth/models/utilisateur-support.table.ts | 10 ++ .../auth/models/utilisateur-verifie.table.ts | 10 ++ .../src/auth/services/auth.service.spec.ts | 91 +++++----- backend/src/auth/services/auth.service.ts | 157 +++++++++++++++--- 10 files changed, 307 insertions(+), 91 deletions(-) create mode 100644 backend/src/auth/models/auth-users.table.ts create mode 100644 backend/src/auth/models/dcp.table.ts rename backend/src/auth/models/{auth.models.ts => private-utilisateur-droit.table.ts} (57%) create mode 100644 backend/src/auth/models/supabase-jwt.models.ts create mode 100644 backend/src/auth/models/utilisateur-support.table.ts create mode 100644 backend/src/auth/models/utilisateur-verifie.table.ts diff --git a/backend/src/auth/auth.module.ts b/backend/src/auth/auth.module.ts index 1ac7a4ea71..3e5659590f 100644 --- a/backend/src/auth/auth.module.ts +++ b/backend/src/auth/auth.module.ts @@ -4,6 +4,7 @@ import { JwtModule } from '@nestjs/jwt'; import { CommonModule } from '../common/common.module'; import { AuthGuard } from './guards/auth.guard'; import { AuthService } from './services/auth.service'; +import { CollectivitesModule } from '../collectivites/collectivites.module'; import { ConfigurationModule } from '../config/configuration.module'; @Module({ @@ -14,6 +15,7 @@ import { ConfigurationModule } from '../config/configuration.module'; }), ConfigurationModule, CommonModule, + CollectivitesModule, ], providers: [ { diff --git a/backend/src/auth/guards/auth.guard.ts b/backend/src/auth/guards/auth.guard.ts index f7dbcb06b2..51ee94ce51 100644 --- a/backend/src/auth/guards/auth.guard.ts +++ b/backend/src/auth/guards/auth.guard.ts @@ -11,7 +11,7 @@ import { Request } from 'express'; import BackendConfigurationService from '../../config/configuration.service'; import { getErrorMessage } from '../../common/services/errors.helper'; import { PublicEndpoint } from '../decorators/public-endpoint.decorator'; -import { SupabaseJwtPayload } from '../models/auth.models'; +import { SupabaseJwtPayload } from '../models/supabase-jwt.models'; @Injectable() export class AuthGuard implements CanActivate { diff --git a/backend/src/auth/models/auth-users.table.ts b/backend/src/auth/models/auth-users.table.ts new file mode 100644 index 0000000000..e3b1b16ad2 --- /dev/null +++ b/backend/src/auth/models/auth-users.table.ts @@ -0,0 +1,52 @@ +import { pgSchema } from 'drizzle-orm/pg-core'; +import { timestamp, uuid, varchar } from 'drizzle-orm/pg-core'; + +export const authSchemaDB = pgSchema('auth'); + +export const authUsersTable = authSchemaDB.table('users', { + id: uuid('user_id').primaryKey().notNull(), + email: varchar('email', { length: 255 }), + createdAt: timestamp('created_at', { withTimezone: true, mode: 'string' }), + lastSignInAt: timestamp('last_sign_in_at', { + withTimezone: true, + mode: 'string', + }), + + /* + TODO + instance_id uuid, + aud varchar(255), + role varchar(255), + encrypted_password varchar(255), + email_confirmed_at timestamp with time zone, + invited_at timestamp with time zone, + confirmation_token varchar(255), + confirmation_sent_at timestamp with time zone, + recovery_token varchar(255), + recovery_sent_at timestamp with time zone, + email_change_token_new varchar(255), + email_change varchar(255), + email_change_sent_at timestamp with time zone, + raw_app_meta_data jsonb, + raw_user_meta_data jsonb, + is_super_admin boolean, + updated_at timestamp with time zone, + phone text default NULL::character varying +unique, + phone_confirmed_at timestamp with time zone, + phone_change text default ''::character varying, + phone_change_token varchar(255) default ''::character varying, + phone_change_sent_at timestamp with time zone, + confirmed_at timestamp with time zone generated always as (LEAST(email_confirmed_at, phone_confirmed_at)) stored, + email_change_token_current varchar(255) default ''::character varying, + email_change_confirm_status smallint default 0 +constraint users_email_change_confirm_status_check +check ((email_change_confirm_status >= 0) AND (email_change_confirm_status <= 2)), +banned_until timestamp with time zone, + reauthentication_token varchar(255) default ''::character varying, + reauthentication_sent_at timestamp with time zone, + is_sso_user boolean default false not null, + deleted_at timestamp with time zone, + is_anonymous boolean default false not null + */ +}); diff --git a/backend/src/auth/models/dcp.table.ts b/backend/src/auth/models/dcp.table.ts new file mode 100644 index 0000000000..3a2df3f3dd --- /dev/null +++ b/backend/src/auth/models/dcp.table.ts @@ -0,0 +1,22 @@ +import { boolean, pgTable, uuid, varchar } from 'drizzle-orm/pg-core'; +import { text, timestamp } from 'drizzle-orm/pg-core'; + +export const dcpTable = pgTable('dcp', { + userId: uuid('user_id').primaryKey().notNull(), // TODO .references(() => users.id), + nom: text('nom').notNull(), + prenom: text('prenom').notNull(), + email: text('email').notNull(), + limited: boolean('limited').default(false).notNull(), + deleted: boolean('deleted').default(false).notNull(), + createdAt: timestamp('created_at', { withTimezone: true, mode: 'string' }) + .defaultNow() + .notNull(), + modifiedAt: timestamp('modified_at', { withTimezone: true, mode: 'string' }) + .defaultNow() + .notNull(), + telephone: varchar('telephone', { length: 30 }), + cguAccepteesLe: timestamp('cgu_acceptees_le', { + withTimezone: true, + mode: 'string', + }), +}); diff --git a/backend/src/auth/models/auth.models.ts b/backend/src/auth/models/private-utilisateur-droit.table.ts similarity index 57% rename from backend/src/auth/models/auth.models.ts rename to backend/src/auth/models/private-utilisateur-droit.table.ts index 9687f45a44..1184bc1edb 100644 --- a/backend/src/auth/models/auth.models.ts +++ b/backend/src/auth/models/private-utilisateur-droit.table.ts @@ -8,8 +8,8 @@ import { timestamp, uuid, } from 'drizzle-orm/pg-core'; +import { collectiviteTable } from '../../collectivites/models/collectivite.table'; import { default as jwt } from 'jsonwebtoken'; -import { collectiviteTable } from '../../collectivites/models/collectivite.models'; export enum NiveauAcces { LECTURE = 'lecture', @@ -26,21 +26,21 @@ export const niveauAccessEnum = pgEnum('niveau_acces', niveauAccessOrdonne); export const utilisateurDroitTable = pgTable('private_utilisateur_droit', { id: serial('id').primaryKey(), - user_id: uuid('user_id').notNull(), // TODO: reference user table - collectivite_id: integer('collectivite_id') + userId: uuid('user_id').notNull(), // TODO: reference user table + collectiviteId: integer('collectivite_id') .notNull() .references(() => collectiviteTable.id), - created_at: timestamp('created_at', { withTimezone: true }) + createdAt: timestamp('created_at', { withTimezone: true }) .default(sql.raw(`CURRENT_TIMESTAMP`)) .notNull(), - modified_at: timestamp('modified_at', { withTimezone: true }).default( - sql.raw(`CURRENT_TIMESTAMP`) + modifiedAt: timestamp('modified_at', { withTimezone: true }).default( + sql.raw(`CURRENT_TIMESTAMP`), ), active: boolean('active').notNull(), - niveau_acces: niveauAccessEnum('niveau_acces') + niveauAcces: niveauAccessEnum('niveau_acces') .notNull() .default(NiveauAcces.LECTURE), - invitation_id: uuid('invitation_id'), // TODO: reference invitation table + invitationId: uuid('invitation_id'), // TODO: reference invitation table }); export type UtilisateurDroitType = InferSelectModel< typeof utilisateurDroitTable @@ -48,21 +48,3 @@ export type UtilisateurDroitType = InferSelectModel< export type CreateUtilisateurDroitType = InferInsertModel< typeof utilisateurDroitTable >; - -export enum SupabaseRole { - AUTHENTICATED = 'authenticated', - SERVICE_ROLE = 'service_role', - ANON = 'anon', // Anonymous -} - -export interface SupabaseJwtPayload extends jwt.JwtPayload { - email?: string; - phone?: string; - app_metadata?: { - provider: string; - providers: string[]; - }; - session_id: string; - role: SupabaseRole; - is_anonymous: boolean; -} diff --git a/backend/src/auth/models/supabase-jwt.models.ts b/backend/src/auth/models/supabase-jwt.models.ts new file mode 100644 index 0000000000..44054a5b75 --- /dev/null +++ b/backend/src/auth/models/supabase-jwt.models.ts @@ -0,0 +1,18 @@ +import * as jwt from 'jsonwebtoken'; + +export enum SupabaseRole { + AUTHENTICATED = 'authenticated', + SERVICE_ROLE = 'service_role', + ANON = 'anon', // Anonymous +} +export interface SupabaseJwtPayload extends jwt.JwtPayload { + email?: string; + phone?: string; + app_metadata?: { + provider: string; + providers: string[]; + }; + session_id: string; + role: SupabaseRole; + is_anonymous: boolean; +} \ No newline at end of file diff --git a/backend/src/auth/models/utilisateur-support.table.ts b/backend/src/auth/models/utilisateur-support.table.ts new file mode 100644 index 0000000000..339f1192fe --- /dev/null +++ b/backend/src/auth/models/utilisateur-support.table.ts @@ -0,0 +1,10 @@ +import { boolean, pgTable, uuid } from 'drizzle-orm/pg-core'; +import { dcpTable } from './dcp.table'; + +export const utilisateurSupportTable = pgTable('utilisateur_support', { + userId: uuid('user_id') + .primaryKey() + .notNull() + .references(() => dcpTable.userId, { onDelete: 'cascade' }), + support: boolean('support').default(false).notNull(), +}); diff --git a/backend/src/auth/models/utilisateur-verifie.table.ts b/backend/src/auth/models/utilisateur-verifie.table.ts new file mode 100644 index 0000000000..7961405d24 --- /dev/null +++ b/backend/src/auth/models/utilisateur-verifie.table.ts @@ -0,0 +1,10 @@ +import { boolean, pgTable, uuid } from 'drizzle-orm/pg-core'; +import { dcpTable } from './dcp.table'; + +export const utilisateurVerifieTable = pgTable('utilisateur_verifie', { + userId: uuid('user_id') + .primaryKey() + .notNull() + .references(() => dcpTable.userId, { onDelete: 'cascade' }), + verifie: boolean('verifie').default(false).notNull(), +}); diff --git a/backend/src/auth/services/auth.service.spec.ts b/backend/src/auth/services/auth.service.spec.ts index d045e86ce9..2255836923 100644 --- a/backend/src/auth/services/auth.service.spec.ts +++ b/backend/src/auth/services/auth.service.spec.ts @@ -2,10 +2,11 @@ import { Test } from '@nestjs/testing'; import DatabaseService from '../../common/services/database.service'; import { NiveauAcces, - SupabaseRole, UtilisateurDroitType, -} from '../models/auth.models'; +} from '../models/private-utilisateur-droit.table'; import { AuthService } from './auth.service'; +import { SupabaseRole } from '../models/supabase-jwt.models'; +import CollectivitesService from '../../collectivites/services/collectivites.service'; describe('AuthService', () => { let authService: AuthService; @@ -15,7 +16,7 @@ describe('AuthService', () => { controllers: [AuthService], }) .useMocker((token) => { - if (token === DatabaseService) { + if (token === DatabaseService || token === CollectivitesService) { return {}; } }) @@ -62,23 +63,23 @@ describe('AuthService', () => { const droits: UtilisateurDroitType[] = [ { id: 1, - user_id: '1', - collectivite_id: 1, - niveau_acces: NiveauAcces.EDITION, + userId: '1', + collectiviteId: 1, + niveauAcces: NiveauAcces.EDITION, active: true, - created_at: new Date(), - modified_at: null, - invitation_id: null, + createdAt: new Date(), + modifiedAt: null, + invitationId: null, }, { id: 1, - user_id: '1', - collectivite_id: 2, - niveau_acces: NiveauAcces.ADMIN, + userId: '1', + collectiviteId: 2, + niveauAcces: NiveauAcces.ADMIN, active: true, - created_at: new Date(), - modified_at: null, - invitation_id: null, + createdAt: new Date(), + modifiedAt: null, + invitationId: null, }, ]; @@ -96,23 +97,23 @@ describe('AuthService', () => { const droits: UtilisateurDroitType[] = [ { id: 1, - user_id: '1', - collectivite_id: 1, - niveau_acces: NiveauAcces.EDITION, + userId: '1', + collectiviteId: 1, + niveauAcces: NiveauAcces.EDITION, active: true, - created_at: new Date(), - modified_at: null, - invitation_id: null, + createdAt: new Date(), + modifiedAt: null, + invitationId: null, }, { id: 1, - user_id: '1', - collectivite_id: 2, - niveau_acces: NiveauAcces.ADMIN, + userId: '1', + collectiviteId: 2, + niveauAcces: NiveauAcces.ADMIN, active: false, - created_at: new Date(), - modified_at: null, - invitation_id: null, + createdAt: new Date(), + modifiedAt: null, + invitationId: null, }, ]; @@ -130,23 +131,23 @@ describe('AuthService', () => { const droits: UtilisateurDroitType[] = [ { id: 1, - user_id: '1', - collectivite_id: 1, - niveau_acces: NiveauAcces.LECTURE, + userId: '1', + collectiviteId: 1, + niveauAcces: NiveauAcces.LECTURE, active: true, - created_at: new Date(), - modified_at: null, - invitation_id: null, + createdAt: new Date(), + modifiedAt: null, + invitationId: null, }, { id: 1, - user_id: '1', - collectivite_id: 2, - niveau_acces: NiveauAcces.ADMIN, + userId: '1', + collectiviteId: 2, + niveauAcces: NiveauAcces.ADMIN, active: true, - created_at: new Date(), - modified_at: null, - invitation_id: null, + createdAt: new Date(), + modifiedAt: null, + invitationId: null, }, ]; @@ -164,13 +165,13 @@ describe('AuthService', () => { const droits: UtilisateurDroitType[] = [ { id: 1, - user_id: '1', - collectivite_id: 2, - niveau_acces: NiveauAcces.EDITION, + userId: '1', + collectiviteId: 2, + niveauAcces: NiveauAcces.EDITION, active: true, - created_at: new Date(), - modified_at: null, - invitation_id: null, + createdAt: new Date(), + modifiedAt: null, + invitationId: null, }, ]; diff --git a/backend/src/auth/services/auth.service.ts b/backend/src/auth/services/auth.service.ts index 75b081dcf3..da58807d08 100644 --- a/backend/src/auth/services/auth.service.ts +++ b/backend/src/auth/services/auth.service.ts @@ -4,27 +4,38 @@ import DatabaseService from '../../common/services/database.service'; import { NiveauAcces, niveauAccessOrdonne, - SupabaseJwtPayload, - SupabaseRole, utilisateurDroitTable, UtilisateurDroitType, -} from '../models/auth.models'; +} from '../models/private-utilisateur-droit.table'; +import { + SupabaseJwtPayload, + SupabaseRole, +} from '../models/supabase-jwt.models'; +import CollectivitesService from '../../collectivites/services/collectivites.service'; +import { utilisateurSupportTable } from '../models/utilisateur-support.table'; +import { utilisateurVerifieTable } from '../models/utilisateur-verifie.table'; +import { userCrm } from '../models/user-crm.dto'; +import { dcpTable } from '../models/dcp.table'; +import { authUsersTable } from '../models/auth-users.table'; @Injectable() export class AuthService { private readonly logger = new Logger(AuthService.name); - constructor(private readonly databaseService: DatabaseService) {} + constructor( + private readonly databaseService: DatabaseService, + private readonly collectiviteService: CollectivitesService, + ) {} aDroitsSuffisants( tokenRole: SupabaseRole, droits: UtilisateurDroitType[], collectiviteIds: number[], - niveauAccessMinimum: NiveauAcces + niveauAccessMinimum: NiveauAcces, ): boolean { if (tokenRole === SupabaseRole.SERVICE_ROLE) { this.logger.log( - `Rôle de service détecté, accès autorisé à toutes les collectivités` + `Rôle de service détecté, accès autorisé à toutes les collectivités`, ); return true; } else if (tokenRole === SupabaseRole.AUTHENTICATED) { @@ -34,28 +45,28 @@ export class AuthService { for (const collectiviteId of collectiviteIds) { const droit = droits.find( (droit) => - droit.collectivite_id.toString() === collectiviteId.toString() // Etrangement collectiviteId est un string + droit.collectiviteId.toString() === collectiviteId.toString(), // Etrangement collectiviteId est un string ); if (!droit) { this.logger.log( - `Droit introuvable pour la collectivité ${collectiviteId}` + `Droit introuvable pour la collectivité ${collectiviteId}`, ); return false; } if (!droit.active) { this.logger.log( - `Droit inactif pour la collectivité ${collectiviteId} et l'utilisateur ${droit.user_id}` + `Droit inactif pour la collectivité ${collectiviteId} et l'utilisateur ${droit.userId}`, ); return false; } const droitNiveauAccessIndex = niveauAccessOrdonne.indexOf( - droit.niveau_acces + droit.niveauAcces, ); if (droitNiveauAccessIndex < niveauAccessMinimumIndex) { this.logger.log( - `Niveau d'accès insuffisant pour la collectivité ${collectiviteId} et l'utilisateur ${droit.user_id} (niveau d'accès: ${droit.niveau_acces}, demandé: ${niveauAccessMinimum})` + `Niveau d'accès insuffisant pour la collectivité ${collectiviteId} et l'utilisateur ${droit.userId} (niveau d'accès: ${droit.niveauAcces}, demandé: ${niveauAccessMinimum})`, ); return false; } @@ -67,19 +78,17 @@ export class AuthService { async getDroitsUtilisateur( userId: string, - collectiviteIds?: number[] + collectiviteIds?: number[], ): Promise { this.logger.log( - `Récupération des droits de l'utilisateur ${userId} et les collectivités ${collectiviteIds?.join( - ', ' - )}` + `Récupération des droits de l'utilisateur ${userId} et les collectivités ${collectiviteIds?.join(', ')}`, ); const conditions: (SQLWrapper | SQL)[] = [ - eq(utilisateurDroitTable.user_id, userId), + eq(utilisateurDroitTable.userId, userId), ]; if (collectiviteIds?.length) { conditions.push( - inArray(utilisateurDroitTable.collectivite_id, collectiviteIds) + inArray(utilisateurDroitTable.collectiviteId, collectiviteIds), ); } const droits = await this.databaseService.db @@ -94,7 +103,7 @@ export class AuthService { tokenInfo: SupabaseJwtPayload, collectiviteIds: number[], niveauAccessMinimum: NiveauAcces, - doNotThrow?: boolean + doNotThrow?: boolean, ): Promise { let droits: UtilisateurDroitType[] = []; const userId = tokenInfo?.sub; @@ -105,11 +114,121 @@ export class AuthService { tokenInfo?.role, droits, collectiviteIds, - niveauAccessMinimum + niveauAccessMinimum, ); if (!authorise && !doNotThrow) { throw new UnauthorizedException(`Droits insuffisants`); } return authorise; } + + /** + * Vérifie si l'utilisateur a un rôle support + * @param tokenInfo token de l'utilisateur + * @return vrai si l'utilisateur a un rôle support + */ + async estSupport(tokenInfo: SupabaseJwtPayload): Promise { + const userId = tokenInfo.sub; + if (tokenInfo.role === SupabaseRole.AUTHENTICATED && userId) { + const result = await this.databaseService.db + .select() + .from(utilisateurSupportTable) + .where(eq(utilisateurSupportTable.userId, userId)); + return result[0].support || false; + } + return false; + } + + /** + * Vérifie si l'utilisateur est vérifié + * @param tokenInfo token de l'utilisateur + * @return vrai si l'utilisateur est vérifié + */ + async estVerifie(tokenInfo: SupabaseJwtPayload): Promise { + const userId = tokenInfo.sub; + if (tokenInfo.role === SupabaseRole.AUTHENTICATED && userId) { + const result = await this.databaseService.db + .select() + .from(utilisateurVerifieTable) + .where(eq(utilisateurVerifieTable.userId, userId)); + return result[0].verifie || false; + } + return false; + } + + /** + * Vérifie si un utilisateur a accès en lecture à une collectivité + * en prenant en compte la restriction possible de la collectivité + * @param tokenInfo token de l'utilisateur + * @param collectiviteId identifiant de la collectivité + * @param doNotThrow vrai pour ne pas générer une exception + */ + async verifieAccesRestreintCollectivite( + tokenInfo: SupabaseJwtPayload, + collectiviteId: number, + doNotThrow?: boolean, + ): Promise { + if (tokenInfo.role === SupabaseRole.SERVICE_ROLE) { + this.logger.log( + `Rôle de service détecté, accès autorisé à toutes les collectivités`, + ); + return true; + } else if (tokenInfo.role === SupabaseRole.AUTHENTICATED) { + let authorise = false; + const collectivite = + await this.collectiviteService.getCollectivite(collectiviteId); + if (collectivite.collectivite.accessRestreint) { + // Si la collectivité est en accès restreint, l'utilisateur doit : + // avoir un droit en lecture sur la collectivité, ou avoir un rôle support, + // ou être un auditeur d'un audit courant de la collectivité. + authorise = + (await this.verifieAccesAuxCollectivites( + tokenInfo, + [collectiviteId], + NiveauAcces.LECTURE, + doNotThrow, + )) || (await this.estSupport(tokenInfo)); // TODO || private.est_auditeur(collectivite_id) + } else { + // Si la collectivité n'est pas en accès restreint, l'utilisateur doit : + // être vérifié, ou s'il ne l'est pas, avoir un droit en lecture sur la collectivité. + authorise = + (await this.estVerifie(tokenInfo)) || + (await this.verifieAccesAuxCollectivites( + tokenInfo, + [collectiviteId], + NiveauAcces.LECTURE, + doNotThrow, + )); + } + if (!authorise && !doNotThrow) { + throw new UnauthorizedException(`Droits insuffisants`); + } + return authorise; + } + return false; + } + + /** + * Récupère les informations de l'utilisateur utiles pour le dialogue avec des crms + * @param tokenInfo token de l'utilisateur + * @return les informations crm de l'utilisateur + */ + async getUserCrmInfo(tokenInfo: SupabaseJwtPayload): Promise { + if (tokenInfo.sub) { + const result = await this.databaseService.db + .select({ + prenom: dcpTable.prenom, + nom: dcpTable.nom, + email: dcpTable.email, + telephone: dcpTable.telephone, + creation: authUsersTable.createdAt, + derniereConnexion: authUsersTable.lastSignInAt, + }) + .from(dcpTable) + .innerJoin(authUsersTable, eq(dcpTable.userId, authUsersTable.id)) + .where(eq(dcpTable.userId, tokenInfo.sub)); + return result[0] || null; + } + return null; + } } From 19efad0831a94b9c8347c1f23f2d25a91d33cbb8 Mon Sep 17 00:00:00 2001 From: Amandine Date: Wed, 25 Sep 2024 15:14:20 +0200 Subject: [PATCH 19/22] =?UTF-8?q?Backend=20-=20Ajoute=20les=20comp=C3=A9te?= =?UTF-8?q?nces=20banatics?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../collectivite-banatic-competence.table.ts | 24 +++++++++++++++++++ .../action-impact-banatic-competence.table.ts | 24 +++++++++++++++++++ .../models/banatic-competence.table.ts | 6 +++++ 3 files changed, 54 insertions(+) create mode 100644 backend/src/collectivites/models/collectivite-banatic-competence.table.ts create mode 100644 backend/src/panier/models/action-impact-banatic-competence.table.ts create mode 100644 backend/src/taxonomie/models/banatic-competence.table.ts diff --git a/backend/src/collectivites/models/collectivite-banatic-competence.table.ts b/backend/src/collectivites/models/collectivite-banatic-competence.table.ts new file mode 100644 index 0000000000..0ceb9dceba --- /dev/null +++ b/backend/src/collectivites/models/collectivite-banatic-competence.table.ts @@ -0,0 +1,24 @@ +import { integer, pgTable } from 'drizzle-orm/pg-core'; +import { collectiviteTable } from './collectivite.table'; +import { primaryKey } from 'drizzle-orm/pg-core'; +import { banaticCompetenceTable } from '../../taxonomie/models/banatic-competence.table'; + +export const collectiviteBanaticCompetenceTable = pgTable( + 'collectivite_banatic_competence', + { + collectiviteId: integer('collectivite_id') + .notNull() + .references(() => collectiviteTable.id), + competenceCode: integer('competence_code') + .notNull() + .references(() => banaticCompetenceTable.code), + }, + (table) => { + return { + collectiviteBanaticCompetencePkey: primaryKey({ + columns: [table.collectiviteId, table.competenceCode], + name: 'collectivite_banatic_competence_pkey', + }), + }; + }, +); diff --git a/backend/src/panier/models/action-impact-banatic-competence.table.ts b/backend/src/panier/models/action-impact-banatic-competence.table.ts new file mode 100644 index 0000000000..9fd4665ad8 --- /dev/null +++ b/backend/src/panier/models/action-impact-banatic-competence.table.ts @@ -0,0 +1,24 @@ +import { integer, pgTable } from 'drizzle-orm/pg-core'; +import { primaryKey } from 'drizzle-orm/pg-core'; +import { actionImpactTable } from './action-impact.table'; +import { banaticCompetenceTable } from '../../taxonomie/models/banatic-competence.table'; + +export const actionImpactBanaticCompetenceTable = pgTable( + 'action_impact_banatic_competence', + { + actionImpactId: integer('action_impact_id') + .notNull() + .references(() => actionImpactTable.id), + competenceCode: integer('competence_code') + .notNull() + .references(() => banaticCompetenceTable.code), + }, + (table) => { + return { + action_impact_banatic_competence_pkey: primaryKey({ + columns: [table.actionImpactId, table.competenceCode], + name: 'action_impact_banatic_competence_pkey', + }), + }; + }, +); diff --git a/backend/src/taxonomie/models/banatic-competence.table.ts b/backend/src/taxonomie/models/banatic-competence.table.ts new file mode 100644 index 0000000000..b1adf51789 --- /dev/null +++ b/backend/src/taxonomie/models/banatic-competence.table.ts @@ -0,0 +1,6 @@ +import { integer, pgTable, text } from 'drizzle-orm/pg-core'; + +export const banaticCompetenceTable = pgTable('banatic_competence', { + code: integer('code').primaryKey().notNull(), + nom: text('nom').notNull(), +}); From 21c722bcfc97f6b12037cb28fbb3546c8e72265d Mon Sep 17 00:00:00 2001 From: Amandine Date: Thu, 10 Oct 2024 12:24:59 +0200 Subject: [PATCH 20/22] Revert "Front - Panier - WIP - Change le realtime de supabase par websocket" This reverts commit 16d680b65edc0dc40fea9964b6bc1a81ab269f58. --- packages/panier/components/PanierRealtime/index.tsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/panier/components/PanierRealtime/index.tsx b/packages/panier/components/PanierRealtime/index.tsx index 66f24852ec..c70890b4f2 100644 --- a/packages/panier/components/PanierRealtime/index.tsx +++ b/packages/panier/components/PanierRealtime/index.tsx @@ -58,14 +58,9 @@ const PanierRealtime = ({ }, [panier.collectivite_preset, setCollectiviteId]); useEffect(() => { - const socket: Socket = io('http://localhost:3000'); - socket.on('panierUpdate', (panierId) => { - if (panierId === panier.id) { - router.refresh(); - } - }); + const channel = panierAPI.listenToPanierUpdates(panier.id, router.refresh); return () => { - socket.disconnect(); + supabase.removeChannel(channel); }; }, [router, panier.id, setUser]); From 1fa92f56e89843c4ab8ed0d726c3b7c7e399fac1 Mon Sep 17 00:00:00 2001 From: Amandine Jacquelin Date: Tue, 22 Oct 2024 18:06:41 +0200 Subject: [PATCH 21/22] =?UTF-8?q?Ajoute=20les=20d=C3=A9pendances=20pour=20?= =?UTF-8?q?websocket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 + pnpm-lock.yaml | 570 ++++++++++++++++++++++++++++++------------------- 2 files changed, 350 insertions(+), 222 deletions(-) diff --git a/package.json b/package.json index 727fea5275..b58d58b513 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "@nestjs/jwt": "^10.2.0", "@nestjs/platform-express": "^10.4.4", "@nestjs/swagger": "^7.4.2", + "@nestjs/websockets": "^10.4.5", "@next/mdx": "^13.5.6", "@next/third-parties": "^14.2.13", "@nivo/axes": "^0.81.0", @@ -100,6 +101,7 @@ "rxjs": "^7.8.0", "sharp": "^0.33.4", "slugify": "^1.6.6", + "socket.io": "^4.8.0", "swr": "^2.2.0", "tailwindcss": "^3.4.8", "ts-case-convert": "^2.0.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c62fb73cb0..8aa619d222 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,7 +10,7 @@ importers: dependencies: '@anatine/zod-nestjs': specifier: ^2.0.9 - version: 2.0.9(@anatine/zod-openapi@2.2.6(openapi3-ts@4.4.0)(zod@3.23.8))(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/swagger@7.4.2(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1))(reflect-metadata@0.1.14))(openapi3-ts@4.4.0)(zod@3.23.8) + version: 2.0.9(@anatine/zod-openapi@2.2.6(openapi3-ts@4.4.0)(zod@3.23.8))(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/swagger@7.4.2(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4)(reflect-metadata@0.1.14))(openapi3-ts@4.4.0)(zod@3.23.8) '@anatine/zod-openapi': specifier: ^2.2.6 version: 2.2.6(openapi3-ts@4.4.0)(zod@3.23.8) @@ -34,7 +34,7 @@ importers: version: 3.9.0(react-hook-form@7.53.0(react@18.3.1)) '@mdx-js/loader': specifier: ^2.3.0 - version: 2.3.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + version: 2.3.0(webpack@5.95.0) '@mdx-js/react': specifier: ^3.0.1 version: 3.0.1(@types/react@18.3.1)(react@18.3.1) @@ -49,7 +49,7 @@ importers: version: 3.2.3(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(rxjs@7.8.1) '@nestjs/core': specifier: ^10.0.2 - version: 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1) + version: 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(@nestjs/websockets@10.4.5)(reflect-metadata@0.1.14)(rxjs@7.8.1) '@nestjs/jwt': specifier: ^10.2.0 version: 10.2.0(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1)) @@ -58,46 +58,49 @@ importers: version: 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4) '@nestjs/swagger': specifier: ^7.4.2 - version: 7.4.2(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1))(reflect-metadata@0.1.14) + version: 7.4.2(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4)(reflect-metadata@0.1.14) + '@nestjs/websockets': + specifier: ^10.4.5 + version: 10.4.5(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1) '@next/mdx': specifier: ^13.5.6 - version: 13.5.7(@mdx-js/loader@2.3.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(@mdx-js/react@3.0.1(@types/react@18.3.1)(react@18.3.1)) + version: 13.5.7(@mdx-js/loader@2.3.0(webpack@5.95.0))(@mdx-js/react@3.0.1(@types/react@18.3.1)(react@18.3.1)) '@next/third-parties': specifier: ^14.2.13 version: 14.2.13(next@14.2.13(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.3))(react@18.3.1) '@nivo/axes': specifier: ^0.81.0 - version: 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@nivo/bar': specifier: ^0.81.0 - version: 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@nivo/core': specifier: ^0.81.0 version: 0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@nivo/geo': specifier: ^0.81.0 - version: 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@nivo/legends': specifier: ^0.81.0 - version: 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1) + version: 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1) '@nivo/line': specifier: ^0.81.0 - version: 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@nivo/pie': specifier: ^0.81.0 - version: 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@nivo/stream': specifier: ^0.81.0 - version: 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@nivo/waffle': specifier: ^0.81.0 - version: 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spring/web': specifier: ^9.7.4 version: 9.7.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@sentry/nestjs': specifier: ^8.31.0 - version: 8.31.0(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1)) + version: 8.31.0(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4) '@sentry/profiling-node': specifier: ^8.31.0 version: 8.31.0 @@ -293,6 +296,9 @@ importers: slugify: specifier: ^1.6.6 version: 1.6.6 + socket.io: + specifier: ^4.8.0 + version: 4.8.0 swr: specifier: ^2.2.0 version: 2.2.5(react@18.3.1) @@ -329,13 +335,13 @@ importers: version: 7.24.7(@babel/core@7.25.2) '@nestjs/cli': specifier: ^10.4.5 - version: 10.4.5(@swc/cli@0.3.14(@swc/core@1.5.29(@swc/helpers@0.5.13))(chokidar@3.6.0))(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0)) + version: 10.4.5(@swc/cli@0.3.14(@swc/core@1.5.29(@swc/helpers@0.5.13))(chokidar@3.6.0))(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) '@nestjs/schematics': specifier: ^10.1.4 version: 10.1.4(chokidar@3.6.0)(typescript@5.6.2) '@nestjs/testing': specifier: ^10.4.4 - version: 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4)) + version: 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4)(@nestjs/platform-express@10.4.4) '@nx/devkit': specifier: 20.0.1 version: 20.0.1(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))) @@ -353,28 +359,28 @@ importers: version: 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(chokidar@3.6.0)(eslint@8.57.1)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2))(typescript@5.6.2) '@nx/next': specifier: 20.0.1 - version: 20.0.1(@babel/core@7.25.2)(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(esbuild@0.19.12)(eslint@8.57.1)(html-webpack-plugin@5.6.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(next@14.2.13(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.3))(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + version: 20.0.1(@babel/core@7.25.2)(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(esbuild@0.19.12)(eslint@8.57.1)(html-webpack-plugin@5.6.0(webpack@5.95.0))(next@14.2.13(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.3))(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack-cli@5.1.4)(webpack@5.95.0) '@nx/node': specifier: 20.0.1 version: 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(babel-plugin-macros@3.1.0)(eslint@8.57.1)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2))(typescript@5.6.2) '@nx/playwright': specifier: 20.0.1 - version: 20.0.1(@babel/traverse@7.25.6)(@playwright/test@1.47.2)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(esbuild@0.19.12)(eslint@8.57.1)(html-webpack-plugin@5.6.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(vite@5.1.8(@types/node@18.16.9)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0))(vitest@1.6.0(@types/node@18.16.9)(@vitest/ui@1.6.0)(jsdom@20.0.3)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0))(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0)) + version: 20.0.1(@babel/traverse@7.25.6)(@playwright/test@1.47.2)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(esbuild@0.19.12)(eslint@8.57.1)(html-webpack-plugin@5.6.0(webpack@5.95.0))(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(vite@5.1.8(@types/node@18.16.9)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0))(vitest@1.6.0)(webpack-cli@5.1.4) '@nx/react': specifier: 20.0.1 - version: 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(eslint@8.57.1)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + version: 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(eslint@8.57.1)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.95.0) '@nx/storybook': specifier: 20.0.1 version: 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(eslint@8.57.1)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(typescript@5.6.2) '@nx/vite': specifier: 20.0.1 - version: 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(typescript@5.6.2)(vite@5.1.8(@types/node@18.16.9)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0))(vitest@1.6.0(@types/node@18.16.9)(@vitest/ui@1.6.0)(jsdom@20.0.3)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0)) + version: 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(typescript@5.6.2)(vite@5.1.8(@types/node@18.16.9)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0))(vitest@1.6.0) '@nx/web': specifier: 20.0.1 version: 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(typescript@5.6.2) '@nx/webpack': specifier: 20.0.1 - version: 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(esbuild@0.19.12)(html-webpack-plugin@5.6.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0)) + version: 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(esbuild@0.19.12)(html-webpack-plugin@5.6.0(webpack@5.95.0))(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack-cli@5.1.4) '@nx/workspace': specifier: 20.0.1 version: 20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)) @@ -392,25 +398,25 @@ importers: version: 8.3.5(storybook@8.3.5) '@storybook/addon-styling-webpack': specifier: ^1.0.0 - version: 1.0.0(storybook@8.3.5)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + version: 1.0.0(storybook@8.3.5)(webpack@5.95.0) '@storybook/addon-webpack5-compiler-babel': specifier: ^3.0.3 - version: 3.0.3(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + version: 3.0.3(webpack@5.95.0) '@storybook/core-server': specifier: ^8.3.5 version: 8.3.5(storybook@8.3.5) '@storybook/nextjs': specifier: ^8.3.5 - version: 8.3.5(@swc/core@1.5.29(@swc/helpers@0.5.13))(babel-plugin-macros@3.1.0)(esbuild@0.19.12)(next@14.2.13(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.3)(storybook@8.3.5)(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack-dev-server@4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(webpack-hot-middleware@2.26.1)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + version: 8.3.5(@swc/core@1.5.29(@swc/helpers@0.5.13))(babel-plugin-macros@3.1.0)(esbuild@0.19.12)(next@14.2.13(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.3)(storybook@8.3.5)(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4)(webpack-dev-server@4.15.2)(webpack-hot-middleware@2.26.1)(webpack@5.95.0) '@storybook/preset-create-react-app': specifier: ^8.3.5 - version: 8.3.5(react-refresh@0.14.2)(react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/babel__core@7.20.5)(esbuild@0.19.12)(eslint@8.57.1)(react@18.3.1)(sass@1.79.3)(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack-hot-middleware@2.26.1))(storybook@8.3.5)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(webpack-hot-middleware@2.26.1)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + version: 8.3.5(react-refresh@0.14.2)(react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/babel__core@7.20.5)(esbuild@0.19.12)(eslint@8.57.1)(react@18.3.1)(sass@1.79.3)(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4)(webpack-hot-middleware@2.26.1))(storybook@8.3.5)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.15.2)(webpack-hot-middleware@2.26.1)(webpack@5.95.0) '@storybook/react': specifier: ^8.3.5 version: 8.3.5(@storybook/test@8.3.5(storybook@8.3.5))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.5)(typescript@5.6.2) '@storybook/react-webpack5': specifier: ^8.3.5 - version: 8.3.5(@storybook/test@8.3.5(storybook@8.3.5))(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.5)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0)) + version: 8.3.5(@storybook/test@8.3.5(storybook@8.3.5))(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.5)(typescript@5.6.2)(webpack-cli@5.1.4) '@storybook/test-runner': specifier: ^0.19.1 version: 0.19.1(@swc/helpers@0.5.13)(@types/node@18.16.9)(babel-plugin-macros@3.1.0)(storybook@8.3.5)(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2)) @@ -491,7 +497,7 @@ importers: version: 7.18.0(eslint@8.57.1)(typescript@5.6.2) '@vitest/coverage-v8': specifier: ^1.0.4 - version: 1.6.0(vitest@1.6.0(@types/node@18.16.9)(@vitest/ui@1.6.0)(jsdom@20.0.3)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0)) + version: 1.6.0(vitest@1.6.0) '@vitest/ui': specifier: ^1.3.1 version: 1.6.0(vitest@1.6.0) @@ -500,7 +506,7 @@ importers: version: 10.4.20(postcss@8.4.47) css-loader: specifier: ^7.1.2 - version: 7.1.2(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + version: 7.1.2(webpack@5.95.0) drizzle-kit: specifier: ^0.24.2 version: 0.24.2 @@ -539,7 +545,7 @@ importers: version: 8.4.47 postcss-loader: specifier: ^8.1.1 - version: 8.1.1(postcss@8.4.47)(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + version: 8.1.1(postcss@8.4.47)(typescript@5.6.2)(webpack@5.95.0) prettier: specifier: ^2.6.2 version: 2.8.8 @@ -551,7 +557,7 @@ importers: version: 8.3.5 style-loader: specifier: ^4.0.0 - version: 4.0.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + version: 4.0.0(webpack@5.95.0) supabase: specifier: 1.151.1 version: 1.151.1 @@ -560,7 +566,7 @@ importers: version: 7.0.0 ts-loader: specifier: ^9.5.1 - version: 9.5.1(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + version: 9.5.1(typescript@5.6.2)(webpack@5.95.0) ts-node: specifier: 10.9.1 version: 10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2) @@ -2670,6 +2676,18 @@ packages: '@nestjs/platform-express': optional: true + '@nestjs/websockets@10.4.5': + resolution: {integrity: sha512-LbL/HRLWQUBTUPY7swojOHdvokyVGINIiuP/VmRdhob4T751r+9i09z2RqRpP71psuom9mnRHYI1+vT2FABrAw==} + peerDependencies: + '@nestjs/common': ^10.0.0 + '@nestjs/core': ^10.0.0 + '@nestjs/platform-socket.io': ^10.0.0 + reflect-metadata: ^0.1.12 || ^0.2.0 + rxjs: ^7.1.0 + peerDependenciesMeta: + '@nestjs/platform-socket.io': + optional: true + '@next/env@14.2.13': resolution: {integrity: sha512-s3lh6K8cbW1h5Nga7NNeXrbe0+2jIIYK9YaA9T7IufDWnZpozdFUp6Hf0d5rNWUKu4fEuSX2rCKlGjCrtylfDw==} @@ -3516,6 +3534,9 @@ packages: '@sinonjs/fake-timers@8.1.0': resolution: {integrity: sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==} + '@socket.io/component-emitter@3.1.2': + resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} + '@storybook/addon-actions@8.3.5': resolution: {integrity: sha512-t8D5oo+4XfD+F8091wLa2y/CDd/W2lExCeol5Vm1tp5saO+u6f2/d7iykLhTowWV84Uohi3D073uFeyTAlGebg==} peerDependencies: @@ -4160,9 +4181,15 @@ packages: '@types/connect@3.4.38': resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + '@types/cookie@0.4.1': + resolution: {integrity: sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==} + '@types/cookiejar@2.1.5': resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==} + '@types/cors@2.8.17': + resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} + '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} @@ -5147,6 +5174,10 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + base64id@2.0.0: + resolution: {integrity: sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==} + engines: {node: ^4.5.0 || >= 5.9} + basic-auth@2.0.1: resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} engines: {node: '>= 0.8'} @@ -5670,6 +5701,10 @@ packages: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + cookiejar@2.1.4: resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==} @@ -6537,6 +6572,14 @@ packages: endent@2.1.0: resolution: {integrity: sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==} + engine.io-parser@5.2.3: + resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==} + engines: {node: '>=10.0.0'} + + engine.io@6.6.2: + resolution: {integrity: sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==} + engines: {node: '>=10.2.0'} + enhanced-resolve@5.17.1: resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} engines: {node: '>=10.13.0'} @@ -11423,6 +11466,17 @@ packages: snake-case@3.0.4: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} + socket.io-adapter@2.5.5: + resolution: {integrity: sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==} + + socket.io-parser@4.2.4: + resolution: {integrity: sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==} + engines: {node: '>=10.0.0'} + + socket.io@4.8.0: + resolution: {integrity: sha512-8U6BEgGjQOfGz3HHTYaC/L1GaxDCJ/KM0XTkJly0EhZ5U/du9uNEZy4ZgYzEzIqlx2CMm25CrCqr1ck899eLNA==} + engines: {node: '>=10.2.0'} + sockjs@0.3.24: resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} @@ -12966,11 +13020,11 @@ snapshots: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 - '@anatine/zod-nestjs@2.0.9(@anatine/zod-openapi@2.2.6(openapi3-ts@4.4.0)(zod@3.23.8))(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/swagger@7.4.2(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1))(reflect-metadata@0.1.14))(openapi3-ts@4.4.0)(zod@3.23.8)': + '@anatine/zod-nestjs@2.0.9(@anatine/zod-openapi@2.2.6(openapi3-ts@4.4.0)(zod@3.23.8))(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/swagger@7.4.2(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4)(reflect-metadata@0.1.14))(openapi3-ts@4.4.0)(zod@3.23.8)': dependencies: '@anatine/zod-openapi': 2.2.6(openapi3-ts@4.4.0)(zod@3.23.8) '@nestjs/common': 10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1) - '@nestjs/swagger': 7.4.2(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1))(reflect-metadata@0.1.14) + '@nestjs/swagger': 7.4.2(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4)(reflect-metadata@0.1.14) openapi3-ts: 4.4.0 ts-deepmerge: 6.2.1 zod: 3.23.8 @@ -14900,7 +14954,7 @@ snapshots: '@lukeed/csprng@1.1.0': {} - '@mdx-js/loader@2.3.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4))': + '@mdx-js/loader@2.3.0(webpack@5.95.0)': dependencies: '@mdx-js/mdx': 2.3.0 source-map: 0.7.4 @@ -15014,7 +15068,7 @@ snapshots: - supports-color - utf-8-validate - '@module-federation/enhanced@0.6.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4))': + '@module-federation/enhanced@0.6.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.95.0)': dependencies: '@module-federation/bridge-react-webpack-plugin': 0.6.11 '@module-federation/data-prefetch': 0.6.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -15037,7 +15091,7 @@ snapshots: - supports-color - utf-8-validate - '@module-federation/enhanced@0.6.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4))': + '@module-federation/enhanced@0.6.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.95.0)': dependencies: '@module-federation/bridge-react-webpack-plugin': 0.6.6 '@module-federation/data-prefetch': 0.6.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -15338,7 +15392,7 @@ snapshots: '@emnapi/runtime': 1.2.0 '@tybys/wasm-util': 0.9.0 - '@nestjs/cli@10.4.5(@swc/cli@0.3.14(@swc/core@1.5.29(@swc/helpers@0.5.13))(chokidar@3.6.0))(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))': + '@nestjs/cli@10.4.5(@swc/cli@0.3.14(@swc/core@1.5.29(@swc/helpers@0.5.13))(chokidar@3.6.0))(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)': dependencies: '@angular-devkit/core': 17.3.8(chokidar@3.6.0) '@angular-devkit/schematics': 17.3.8(chokidar@3.6.0) @@ -15348,7 +15402,7 @@ snapshots: chokidar: 3.6.0 cli-table3: 0.6.5 commander: 4.1.1 - fork-ts-checker-webpack-plugin: 9.0.2(typescript@5.3.3)(webpack@5.94.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))) + fork-ts-checker-webpack-plugin: 9.0.2(typescript@5.3.3)(webpack@5.94.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) glob: 10.4.2 inquirer: 8.2.6 node-emoji: 1.11.0 @@ -15357,7 +15411,7 @@ snapshots: tsconfig-paths: 4.2.0 tsconfig-paths-webpack-plugin: 4.1.0 typescript: 5.3.3 - webpack: 5.94.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0)) + webpack: 5.94.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) webpack-node-externals: 3.0.0 optionalDependencies: '@swc/cli': 0.3.14(@swc/core@1.5.29(@swc/helpers@0.5.13))(chokidar@3.6.0) @@ -15383,7 +15437,7 @@ snapshots: lodash: 4.17.21 rxjs: 7.8.1 - '@nestjs/core@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1)': + '@nestjs/core@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(@nestjs/websockets@10.4.5)(reflect-metadata@0.1.14)(rxjs@7.8.1)': dependencies: '@nestjs/common': 10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1) '@nuxtjs/opencollective': 0.3.2 @@ -15396,6 +15450,7 @@ snapshots: uid: 2.0.2 optionalDependencies: '@nestjs/platform-express': 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4) + '@nestjs/websockets': 10.4.5(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1) transitivePeerDependencies: - encoding @@ -15413,7 +15468,7 @@ snapshots: '@nestjs/platform-express@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4)': dependencies: '@nestjs/common': 10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1) - '@nestjs/core': 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1) + '@nestjs/core': 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(@nestjs/websockets@10.4.5)(reflect-metadata@0.1.14)(rxjs@7.8.1) body-parser: 1.20.3 cors: 2.8.5 express: 4.21.0 @@ -15454,11 +15509,11 @@ snapshots: transitivePeerDependencies: - chokidar - '@nestjs/swagger@7.4.2(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1))(reflect-metadata@0.1.14)': + '@nestjs/swagger@7.4.2(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4)(reflect-metadata@0.1.14)': dependencies: '@microsoft/tsdoc': 0.15.0 '@nestjs/common': 10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1) - '@nestjs/core': 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1) + '@nestjs/core': 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(@nestjs/websockets@10.4.5)(reflect-metadata@0.1.14)(rxjs@7.8.1) '@nestjs/mapped-types': 2.0.5(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(reflect-metadata@0.1.14) js-yaml: 4.1.0 lodash: 4.17.21 @@ -15466,25 +15521,35 @@ snapshots: reflect-metadata: 0.1.14 swagger-ui-dist: 5.17.14 - '@nestjs/testing@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4))': + '@nestjs/testing@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4)(@nestjs/platform-express@10.4.4)': dependencies: '@nestjs/common': 10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1) - '@nestjs/core': 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1) + '@nestjs/core': 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(@nestjs/websockets@10.4.5)(reflect-metadata@0.1.14)(rxjs@7.8.1) tslib: 2.7.0 optionalDependencies: '@nestjs/platform-express': 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4) + '@nestjs/websockets@10.4.5(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1)': + dependencies: + '@nestjs/common': 10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1) + '@nestjs/core': 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(@nestjs/websockets@10.4.5)(reflect-metadata@0.1.14)(rxjs@7.8.1) + iterare: 1.2.1 + object-hash: 3.0.0 + reflect-metadata: 0.1.14 + rxjs: 7.8.1 + tslib: 2.7.0 + '@next/env@14.2.13': {} '@next/eslint-plugin-next@14.2.13': dependencies: glob: 10.3.10 - '@next/mdx@13.5.7(@mdx-js/loader@2.3.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(@mdx-js/react@3.0.1(@types/react@18.3.1)(react@18.3.1))': + '@next/mdx@13.5.7(@mdx-js/loader@2.3.0(webpack@5.95.0))(@mdx-js/react@3.0.1(@types/react@18.3.1)(react@18.3.1))': dependencies: source-map: 0.7.4 optionalDependencies: - '@mdx-js/loader': 2.3.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + '@mdx-js/loader': 2.3.0(webpack@5.95.0) '@mdx-js/react': 3.0.1(@types/react@18.3.1)(react@18.3.1) '@next/swc-darwin-arm64@14.2.13': @@ -15524,9 +15589,9 @@ snapshots: dependencies: eslint-scope: 5.1.1 - '@nivo/annotations@0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@nivo/annotations@0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@nivo/colors': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1) + '@nivo/colors': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1) '@nivo/core': 0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spring/web': 9.7.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) lodash: 4.17.21 @@ -15535,9 +15600,9 @@ snapshots: - prop-types - react-dom - '@nivo/arcs@0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@nivo/arcs@0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@nivo/colors': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1) + '@nivo/colors': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1) '@nivo/core': 0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spring/web': 9.7.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) d3-shape: 1.3.7 @@ -15546,7 +15611,7 @@ snapshots: - prop-types - react-dom - '@nivo/axes@0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@nivo/axes@0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@nivo/core': 0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@nivo/scales': 0.81.0 @@ -15558,13 +15623,13 @@ snapshots: transitivePeerDependencies: - react-dom - '@nivo/bar@0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@nivo/bar@0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@nivo/annotations': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@nivo/axes': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@nivo/colors': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1) + '@nivo/annotations': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@nivo/axes': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@nivo/colors': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1) '@nivo/core': 0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@nivo/legends': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1) + '@nivo/legends': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1) '@nivo/scales': 0.81.0 '@nivo/tooltip': 0.81.0(@nivo/core@0.81.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spring/web': 9.7.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -15576,7 +15641,7 @@ snapshots: - prop-types - react-dom - '@nivo/colors@0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1)': + '@nivo/colors@0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1)': dependencies: '@nivo/core': 0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) d3-color: 3.1.0 @@ -15604,11 +15669,11 @@ snapshots: transitivePeerDependencies: - react-dom - '@nivo/geo@0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@nivo/geo@0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@nivo/colors': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1) + '@nivo/colors': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1) '@nivo/core': 0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@nivo/legends': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1) + '@nivo/legends': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1) '@nivo/tooltip': 0.81.0(@nivo/core@0.81.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) d3-format: 1.4.5 d3-geo: 1.12.1 @@ -15618,22 +15683,22 @@ snapshots: transitivePeerDependencies: - react-dom - '@nivo/legends@0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1)': + '@nivo/legends@0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1)': dependencies: '@nivo/core': 0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) prop-types: 15.8.1 react: 18.3.1 - '@nivo/line@0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@nivo/line@0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@nivo/annotations': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@nivo/axes': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@nivo/colors': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1) + '@nivo/annotations': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@nivo/axes': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@nivo/colors': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1) '@nivo/core': 0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@nivo/legends': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1) + '@nivo/legends': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1) '@nivo/scales': 0.81.0 '@nivo/tooltip': 0.81.0(@nivo/core@0.81.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@nivo/voronoi': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) + '@nivo/voronoi': 0.81.0(@nivo/core@0.81.0)(react@18.3.1) '@react-spring/web': 9.7.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) d3-shape: 1.3.7 prop-types: 15.8.1 @@ -15641,12 +15706,12 @@ snapshots: transitivePeerDependencies: - react-dom - '@nivo/pie@0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@nivo/pie@0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@nivo/arcs': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@nivo/colors': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1) + '@nivo/arcs': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@nivo/colors': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1) '@nivo/core': 0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@nivo/legends': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1) + '@nivo/legends': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1) '@nivo/tooltip': 0.81.0(@nivo/core@0.81.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) d3-shape: 1.3.7 react: 18.3.1 @@ -15666,12 +15731,12 @@ snapshots: d3-time-format: 3.0.0 lodash: 4.17.21 - '@nivo/stream@0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@nivo/stream@0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@nivo/axes': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@nivo/colors': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1) + '@nivo/axes': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@nivo/colors': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1) '@nivo/core': 0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@nivo/legends': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1) + '@nivo/legends': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1) '@nivo/scales': 0.81.0 '@nivo/tooltip': 0.81.0(@nivo/core@0.81.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@react-spring/web': 9.7.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -15689,18 +15754,18 @@ snapshots: - react - react-dom - '@nivo/voronoi@0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)': + '@nivo/voronoi@0.81.0(@nivo/core@0.81.0)(react@18.3.1)': dependencies: '@nivo/core': 0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) d3-delaunay: 5.3.0 d3-scale: 3.3.0 react: 18.3.1 - '@nivo/waffle@0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@nivo/waffle@0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@nivo/colors': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1) + '@nivo/colors': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1) '@nivo/core': 0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@nivo/legends': 0.81.0(@nivo/core@0.81.0(@nivo/tooltip@0.81.0)(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(prop-types@15.8.1)(react@18.3.1) + '@nivo/legends': 0.81.0(@nivo/core@0.81.0)(prop-types@15.8.1)(react@18.3.1) '@nivo/recompose': 0.81.0(react@18.3.1) '@nivo/tooltip': 0.81.0(@nivo/core@0.81.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) lodash: 4.17.21 @@ -15960,19 +16025,19 @@ snapshots: - typescript - verdaccio - '@nx/next@20.0.1(@babel/core@7.25.2)(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(esbuild@0.19.12)(eslint@8.57.1)(html-webpack-plugin@5.6.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(next@14.2.13(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.3))(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4))': + '@nx/next@20.0.1(@babel/core@7.25.2)(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(esbuild@0.19.12)(eslint@8.57.1)(html-webpack-plugin@5.6.0(webpack@5.95.0))(next@14.2.13(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.3))(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack-cli@5.1.4)(webpack@5.95.0)': dependencies: '@babel/plugin-proposal-decorators': 7.24.7(@babel/core@7.25.2) '@nx/devkit': 20.0.1(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))) '@nx/eslint': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(eslint@8.57.1)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))) '@nx/js': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(typescript@5.6.2) - '@nx/react': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(eslint@8.57.1)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + '@nx/react': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(eslint@8.57.1)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.95.0) '@nx/web': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(typescript@5.6.2) - '@nx/webpack': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(esbuild@0.19.12)(html-webpack-plugin@5.6.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0)) + '@nx/webpack': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(esbuild@0.19.12)(html-webpack-plugin@5.6.0(webpack@5.95.0))(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack-cli@5.1.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.6.2) '@svgr/webpack': 8.1.0(typescript@5.6.2) - copy-webpack-plugin: 10.2.4(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - file-loader: 6.2.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + copy-webpack-plugin: 10.2.4(webpack@5.95.0) + file-loader: 6.2.0(webpack@5.95.0) ignore: 5.3.2 next: 14.2.13(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.3) picocolors: 1.1.0 @@ -16068,13 +16133,13 @@ snapshots: '@nx/nx-win32-x64-msvc@20.0.1': optional: true - '@nx/playwright@20.0.1(@babel/traverse@7.25.6)(@playwright/test@1.47.2)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(esbuild@0.19.12)(eslint@8.57.1)(html-webpack-plugin@5.6.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(vite@5.1.8(@types/node@18.16.9)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0))(vitest@1.6.0(@types/node@18.16.9)(@vitest/ui@1.6.0)(jsdom@20.0.3)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0))(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))': + '@nx/playwright@20.0.1(@babel/traverse@7.25.6)(@playwright/test@1.47.2)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(esbuild@0.19.12)(eslint@8.57.1)(html-webpack-plugin@5.6.0(webpack@5.95.0))(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(vite@5.1.8(@types/node@18.16.9)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0))(vitest@1.6.0)(webpack-cli@5.1.4)': dependencies: '@nx/devkit': 20.0.1(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))) '@nx/eslint': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(eslint@8.57.1)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))) '@nx/js': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(typescript@5.6.2) - '@nx/vite': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(typescript@5.6.2)(vite@5.1.8(@types/node@18.16.9)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0))(vitest@1.6.0(@types/node@18.16.9)(@vitest/ui@1.6.0)(jsdom@20.0.3)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0)) - '@nx/webpack': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(esbuild@0.19.12)(html-webpack-plugin@5.6.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0)) + '@nx/vite': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(typescript@5.6.2)(vite@5.1.8(@types/node@18.16.9)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0))(vitest@1.6.0) + '@nx/webpack': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(esbuild@0.19.12)(html-webpack-plugin@5.6.0(webpack@5.95.0))(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack-cli@5.1.4) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.6.2) minimatch: 9.0.3 tslib: 2.7.0 @@ -16115,9 +16180,9 @@ snapshots: - vue-tsc - webpack-cli - '@nx/react@20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(eslint@8.57.1)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4))': + '@nx/react@20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(eslint@8.57.1)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.95.0)': dependencies: - '@module-federation/enhanced': 0.6.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + '@module-federation/enhanced': 0.6.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.95.0) '@nx/devkit': 20.0.1(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))) '@nx/eslint': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(@zkochan/js-yaml@0.0.7)(eslint@8.57.1)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))) '@nx/js': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(typescript@5.6.2) @@ -16125,7 +16190,7 @@ snapshots: '@phenomnomnominal/tsquery': 5.0.1(typescript@5.6.2) '@svgr/webpack': 8.1.0(typescript@5.6.2) express: 4.21.0 - file-loader: 6.2.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + file-loader: 6.2.0(webpack@5.95.0) http-proxy-middleware: 3.0.3 minimatch: 9.0.3 picocolors: 1.1.0 @@ -16174,7 +16239,7 @@ snapshots: - typescript - verdaccio - '@nx/vite@20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(typescript@5.6.2)(vite@5.1.8(@types/node@18.16.9)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0))(vitest@1.6.0(@types/node@18.16.9)(@vitest/ui@1.6.0)(jsdom@20.0.3)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0))': + '@nx/vite@20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(typescript@5.6.2)(vite@5.1.8(@types/node@18.16.9)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0))(vitest@1.6.0)': dependencies: '@nx/devkit': 20.0.1(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))) '@nx/js': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(typescript@5.6.2) @@ -16217,49 +16282,49 @@ snapshots: - typescript - verdaccio - '@nx/webpack@20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(esbuild@0.19.12)(html-webpack-plugin@5.6.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))': + '@nx/webpack@20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(esbuild@0.19.12)(html-webpack-plugin@5.6.0(webpack@5.95.0))(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack-cli@5.1.4)': dependencies: '@babel/core': 7.25.2 - '@module-federation/enhanced': 0.6.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + '@module-federation/enhanced': 0.6.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.95.0) '@module-federation/sdk': 0.6.11 '@nx/devkit': 20.0.1(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))) '@nx/js': 20.0.1(@babel/traverse@7.25.6)(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(nx@20.0.1(@swc-node/register@1.9.2(@swc/core@1.5.29(@swc/helpers@0.5.13))(@swc/types@0.1.12)(typescript@5.6.2))(@swc/core@1.5.29(@swc/helpers@0.5.13)))(typescript@5.6.2) '@phenomnomnominal/tsquery': 5.0.1(typescript@5.6.2) ajv: 8.17.1 autoprefixer: 10.4.20(postcss@8.4.47) - babel-loader: 9.2.1(@babel/core@7.25.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + babel-loader: 9.2.1(@babel/core@7.25.2)(webpack@5.95.0) browserslist: 4.24.0 chalk: 4.1.2 - copy-webpack-plugin: 10.2.4(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - css-loader: 6.11.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - css-minimizer-webpack-plugin: 5.0.1(esbuild@0.19.12)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + copy-webpack-plugin: 10.2.4(webpack@5.95.0) + css-loader: 6.11.0(webpack@5.95.0) + css-minimizer-webpack-plugin: 5.0.1(esbuild@0.19.12)(webpack@5.95.0) express: 4.21.0 - fork-ts-checker-webpack-plugin: 7.2.13(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + fork-ts-checker-webpack-plugin: 7.2.13(typescript@5.6.2)(webpack@5.95.0) http-proxy-middleware: 3.0.3 less: 4.1.3 - less-loader: 11.1.0(less@4.1.3)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - license-webpack-plugin: 4.0.2(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + less-loader: 11.1.0(less@4.1.3)(webpack@5.95.0) + license-webpack-plugin: 4.0.2(webpack@5.95.0) loader-utils: 2.0.4 - mini-css-extract-plugin: 2.4.7(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + mini-css-extract-plugin: 2.4.7(webpack@5.95.0) parse5: 4.0.0 postcss: 8.4.47 postcss-import: 14.1.0(postcss@8.4.47) - postcss-loader: 6.2.1(postcss@8.4.47)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + postcss-loader: 6.2.1(postcss@8.4.47)(webpack@5.95.0) rxjs: 7.8.1 sass: 1.79.3 - sass-loader: 12.6.0(sass@1.79.3)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - source-map-loader: 5.0.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - style-loader: 3.3.4(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + sass-loader: 12.6.0(sass@1.79.3)(webpack@5.95.0) + source-map-loader: 5.0.0(webpack@5.95.0) + style-loader: 3.3.4(webpack@5.95.0) stylus: 0.59.0 - stylus-loader: 7.1.3(stylus@0.59.0)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - terser-webpack-plugin: 5.3.10(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - ts-loader: 9.5.1(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + stylus-loader: 7.1.3(stylus@0.59.0)(webpack@5.95.0) + terser-webpack-plugin: 5.3.10(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack@5.95.0) + ts-loader: 9.5.1(typescript@5.6.2)(webpack@5.95.0) tsconfig-paths-webpack-plugin: 4.0.0 tslib: 2.7.0 webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) - webpack-dev-server: 5.1.0(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + webpack-dev-server: 5.1.0(webpack-cli@5.1.4)(webpack@5.95.0) webpack-node-externals: 3.0.0 - webpack-subresource-integrity: 5.1.0(html-webpack-plugin@5.6.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + webpack-subresource-integrity: 5.1.0(html-webpack-plugin@5.6.0(webpack@5.95.0))(webpack@5.95.0) transitivePeerDependencies: - '@babel/traverse' - '@parcel/css' @@ -16561,7 +16626,7 @@ snapshots: dependencies: playwright: 1.47.2 - '@pmmmwh/react-refresh-webpack-plugin@0.5.15(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(webpack-hot-middleware@2.26.1)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4))': + '@pmmmwh/react-refresh-webpack-plugin@0.5.15(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.15.2)(webpack-hot-middleware@2.26.1)(webpack@5.95.0)': dependencies: ansi-html: 0.0.9 core-js-pure: 3.38.1 @@ -16574,10 +16639,10 @@ snapshots: webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) optionalDependencies: type-fest: 2.19.0 - webpack-dev-server: 4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + webpack-dev-server: 4.15.2(webpack-cli@5.1.4)(webpack@5.95.0) webpack-hot-middleware: 2.26.1 - '@pmmmwh/react-refresh-webpack-plugin@0.5.15(react-refresh@0.14.2)(type-fest@2.19.0)(webpack-dev-server@4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(webpack-hot-middleware@2.26.1)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4))': + '@pmmmwh/react-refresh-webpack-plugin@0.5.15(react-refresh@0.14.2)(type-fest@2.19.0)(webpack-dev-server@4.15.2)(webpack-hot-middleware@2.26.1)(webpack@5.95.0)': dependencies: ansi-html: 0.0.9 core-js-pure: 3.38.1 @@ -16590,7 +16655,7 @@ snapshots: webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) optionalDependencies: type-fest: 2.19.0 - webpack-dev-server: 4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + webpack-dev-server: 4.15.2(webpack-cli@5.1.4)(webpack@5.95.0) webpack-hot-middleware: 2.26.1 '@polka/url@1.0.0-next.28': {} @@ -16784,10 +16849,10 @@ snapshots: '@sentry/utils': 7.119.0 localforage: 1.10.0 - '@sentry/nestjs@8.31.0(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1))': + '@sentry/nestjs@8.31.0(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/core@10.4.4)': dependencies: '@nestjs/common': 10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1) - '@nestjs/core': 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(reflect-metadata@0.1.14)(rxjs@7.8.1) + '@nestjs/core': 10.4.4(@nestjs/common@10.4.4(reflect-metadata@0.1.14)(rxjs@7.8.1))(@nestjs/platform-express@10.4.4)(@nestjs/websockets@10.4.5)(reflect-metadata@0.1.14)(rxjs@7.8.1) '@sentry/core': 8.31.0 '@sentry/node': 8.31.0 '@sentry/types': 8.31.0 @@ -16913,6 +16978,8 @@ snapshots: dependencies: '@sinonjs/commons': 1.8.6 + '@socket.io/component-emitter@3.1.2': {} + '@storybook/addon-actions@8.3.5(storybook@8.3.5)': dependencies: '@storybook/global': 5.0.0 @@ -16997,7 +17064,7 @@ snapshots: storybook: 8.3.5 ts-dedent: 2.2.0 - '@storybook/addon-styling-webpack@1.0.0(storybook@8.3.5)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4))': + '@storybook/addon-styling-webpack@1.0.0(storybook@8.3.5)(webpack@5.95.0)': dependencies: '@storybook/node-logger': 8.3.3(storybook@8.3.5) webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) @@ -17013,10 +17080,10 @@ snapshots: memoizerific: 1.11.3 storybook: 8.3.5 - '@storybook/addon-webpack5-compiler-babel@3.0.3(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4))': + '@storybook/addon-webpack5-compiler-babel@3.0.3(webpack@5.95.0)': dependencies: '@babel/core': 7.25.2 - babel-loader: 9.2.1(@babel/core@7.25.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + babel-loader: 9.2.1(@babel/core@7.25.2)(webpack@5.95.0) transitivePeerDependencies: - supports-color - webpack @@ -17042,7 +17109,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/builder-webpack5@8.3.5(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(storybook@8.3.5)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))': + '@storybook/builder-webpack5@8.3.5(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(storybook@8.3.5)(typescript@5.6.2)(webpack-cli@5.1.4)': dependencies: '@storybook/core-webpack': 8.3.5(storybook@8.3.5) '@types/node': 22.7.5 @@ -17051,25 +17118,25 @@ snapshots: case-sensitive-paths-webpack-plugin: 2.4.0 cjs-module-lexer: 1.4.1 constants-browserify: 1.0.0 - css-loader: 6.11.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + css-loader: 6.11.0(webpack@5.95.0) es-module-lexer: 1.5.4 express: 4.21.0 - fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.6.2)(webpack@5.95.0) fs-extra: 11.2.0 - html-webpack-plugin: 5.6.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + html-webpack-plugin: 5.6.0(webpack@5.95.0) magic-string: 0.30.11 path-browserify: 1.0.1 process: 0.11.10 semver: 7.6.3 storybook: 8.3.5 - style-loader: 3.3.4(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - terser-webpack-plugin: 5.3.10(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + style-loader: 3.3.4(webpack@5.95.0) + terser-webpack-plugin: 5.3.10(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack@5.95.0) ts-dedent: 2.2.0 url: 0.11.4 util: 0.12.5 util-deprecate: 1.0.2 webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) - webpack-dev-middleware: 6.1.3(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + webpack-dev-middleware: 6.1.3(webpack@5.95.0) webpack-hot-middleware: 2.26.1 webpack-virtual-modules: 0.6.2 optionalDependencies: @@ -17157,7 +17224,7 @@ snapshots: dependencies: storybook: 8.3.5 - '@storybook/nextjs@8.3.5(@swc/core@1.5.29(@swc/helpers@0.5.13))(babel-plugin-macros@3.1.0)(esbuild@0.19.12)(next@14.2.13(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.3)(storybook@8.3.5)(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack-dev-server@4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(webpack-hot-middleware@2.26.1)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4))': + '@storybook/nextjs@8.3.5(@swc/core@1.5.29(@swc/helpers@0.5.13))(babel-plugin-macros@3.1.0)(esbuild@0.19.12)(next@14.2.13(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.3)(storybook@8.3.5)(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4)(webpack-dev-server@4.15.2)(webpack-hot-middleware@2.26.1)(webpack@5.95.0)': dependencies: '@babel/core': 7.25.2 '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.25.2) @@ -17172,32 +17239,32 @@ snapshots: '@babel/preset-react': 7.24.7(@babel/core@7.25.2) '@babel/preset-typescript': 7.24.7(@babel/core@7.25.2) '@babel/runtime': 7.25.6 - '@pmmmwh/react-refresh-webpack-plugin': 0.5.15(react-refresh@0.14.2)(type-fest@2.19.0)(webpack-dev-server@4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(webpack-hot-middleware@2.26.1)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - '@storybook/builder-webpack5': 8.3.5(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(storybook@8.3.5)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0)) - '@storybook/preset-react-webpack': 8.3.5(@storybook/test@8.3.5(storybook@8.3.5))(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.5)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0)) + '@pmmmwh/react-refresh-webpack-plugin': 0.5.15(react-refresh@0.14.2)(type-fest@2.19.0)(webpack-dev-server@4.15.2)(webpack-hot-middleware@2.26.1)(webpack@5.95.0) + '@storybook/builder-webpack5': 8.3.5(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(storybook@8.3.5)(typescript@5.6.2)(webpack-cli@5.1.4) + '@storybook/preset-react-webpack': 8.3.5(@storybook/test@8.3.5(storybook@8.3.5))(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.5)(typescript@5.6.2)(webpack-cli@5.1.4) '@storybook/react': 8.3.5(@storybook/test@8.3.5(storybook@8.3.5))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.5)(typescript@5.6.2) '@storybook/test': 8.3.5(storybook@8.3.5) '@types/node': 22.7.5 '@types/semver': 7.5.8 - babel-loader: 9.2.1(@babel/core@7.25.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - css-loader: 6.11.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + babel-loader: 9.2.1(@babel/core@7.25.2)(webpack@5.95.0) + css-loader: 6.11.0(webpack@5.95.0) find-up: 5.0.0 fs-extra: 11.2.0 image-size: 1.1.1 loader-utils: 3.3.1 next: 14.2.13(@babel/core@7.25.2)(@opentelemetry/api@1.9.0)(@playwright/test@1.47.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.79.3) - node-polyfill-webpack-plugin: 2.0.1(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + node-polyfill-webpack-plugin: 2.0.1(webpack@5.95.0) pnp-webpack-plugin: 1.7.0(typescript@5.6.2) postcss: 8.4.47 - postcss-loader: 8.1.1(postcss@8.4.47)(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + postcss-loader: 8.1.1(postcss@8.4.47)(typescript@5.6.2)(webpack@5.95.0) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-refresh: 0.14.2 resolve-url-loader: 5.0.0 - sass-loader: 13.3.3(sass@1.79.3)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + sass-loader: 13.3.3(sass@1.79.3)(webpack@5.95.0) semver: 7.6.3 storybook: 8.3.5 - style-loader: 3.3.4(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + style-loader: 3.3.4(webpack@5.95.0) styled-jsx: 5.1.6(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react@18.3.1) ts-dedent: 2.2.0 tsconfig-paths: 4.2.0 @@ -17229,13 +17296,13 @@ snapshots: dependencies: storybook: 8.3.5 - '@storybook/preset-create-react-app@8.3.5(react-refresh@0.14.2)(react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/babel__core@7.20.5)(esbuild@0.19.12)(eslint@8.57.1)(react@18.3.1)(sass@1.79.3)(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack-hot-middleware@2.26.1))(storybook@8.3.5)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(webpack-hot-middleware@2.26.1)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4))': + '@storybook/preset-create-react-app@8.3.5(react-refresh@0.14.2)(react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/babel__core@7.20.5)(esbuild@0.19.12)(eslint@8.57.1)(react@18.3.1)(sass@1.79.3)(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4)(webpack-hot-middleware@2.26.1))(storybook@8.3.5)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.15.2)(webpack-hot-middleware@2.26.1)(webpack@5.95.0)': dependencies: - '@pmmmwh/react-refresh-webpack-plugin': 0.5.15(react-refresh@0.14.2)(type-fest@2.19.0)(webpack-dev-server@4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(webpack-hot-middleware@2.26.1)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + '@pmmmwh/react-refresh-webpack-plugin': 0.5.15(react-refresh@0.14.2)(type-fest@2.19.0)(webpack-dev-server@4.15.2)(webpack-hot-middleware@2.26.1)(webpack@5.95.0) + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.95.0) '@types/semver': 7.5.8 pnp-webpack-plugin: 1.7.0(typescript@5.6.2) - react-scripts: 5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/babel__core@7.20.5)(esbuild@0.19.12)(eslint@8.57.1)(react@18.3.1)(sass@1.79.3)(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack-hot-middleware@2.26.1) + react-scripts: 5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/babel__core@7.20.5)(esbuild@0.19.12)(eslint@8.57.1)(react@18.3.1)(sass@1.79.3)(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4)(webpack-hot-middleware@2.26.1) semver: 7.6.3 storybook: 8.3.5 transitivePeerDependencies: @@ -17250,11 +17317,11 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - '@storybook/preset-react-webpack@8.3.5(@storybook/test@8.3.5(storybook@8.3.5))(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.5)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))': + '@storybook/preset-react-webpack@8.3.5(@storybook/test@8.3.5(storybook@8.3.5))(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.5)(typescript@5.6.2)(webpack-cli@5.1.4)': dependencies: '@storybook/core-webpack': 8.3.5(storybook@8.3.5) '@storybook/react': 8.3.5(@storybook/test@8.3.5(storybook@8.3.5))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.5)(typescript@5.6.2) - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.95.0) '@types/node': 22.7.5 '@types/semver': 7.5.8 find-up: 5.0.0 @@ -17286,7 +17353,7 @@ snapshots: dependencies: storybook: 8.3.5 - '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4))': + '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.6.2)(webpack@5.95.0)': dependencies: debug: 4.3.7 endent: 2.1.0 @@ -17306,10 +17373,10 @@ snapshots: react-dom: 18.3.1(react@18.3.1) storybook: 8.3.5 - '@storybook/react-webpack5@8.3.5(@storybook/test@8.3.5(storybook@8.3.5))(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.5)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))': + '@storybook/react-webpack5@8.3.5(@storybook/test@8.3.5(storybook@8.3.5))(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.5)(typescript@5.6.2)(webpack-cli@5.1.4)': dependencies: - '@storybook/builder-webpack5': 8.3.5(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(storybook@8.3.5)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0)) - '@storybook/preset-react-webpack': 8.3.5(@storybook/test@8.3.5(storybook@8.3.5))(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.5)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0)) + '@storybook/builder-webpack5': 8.3.5(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(storybook@8.3.5)(typescript@5.6.2)(webpack-cli@5.1.4) + '@storybook/preset-react-webpack': 8.3.5(@storybook/test@8.3.5(storybook@8.3.5))(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.5)(typescript@5.6.2)(webpack-cli@5.1.4) '@storybook/react': 8.3.5(@storybook/test@8.3.5(storybook@8.3.5))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.3.5)(typescript@5.6.2) '@types/node': 22.7.5 react: 18.3.1 @@ -17873,8 +17940,14 @@ snapshots: dependencies: '@types/node': 18.16.9 + '@types/cookie@0.4.1': {} + '@types/cookiejar@2.1.5': {} + '@types/cors@2.8.17': + dependencies: + '@types/node': 18.16.9 + '@types/debug@4.1.12': dependencies: '@types/ms': 0.7.34 @@ -18384,7 +18457,7 @@ snapshots: '@ungap/structured-clone@1.2.0': {} - '@vitest/coverage-v8@1.6.0(vitest@1.6.0(@types/node@18.16.9)(@vitest/ui@1.6.0)(jsdom@20.0.3)(less@4.1.3)(sass@1.79.3)(stylus@0.59.0)(terser@5.33.0))': + '@vitest/coverage-v8@1.6.0(vitest@1.6.0)': dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 0.2.3 @@ -18551,22 +18624,22 @@ snapshots: '@webassemblyjs/ast': 1.12.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4))': + '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.95.0)': dependencies: webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0) - '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4))': + '@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.95.0)': dependencies: webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0) - '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack-dev-server@4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4))': + '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack-dev-server@4.15.2)(webpack@5.95.0)': dependencies: webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0) optionalDependencies: - webpack-dev-server: 4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + webpack-dev-server: 4.15.2(webpack-cli@5.1.4)(webpack@5.95.0) '@xtuc/ieee754@1.2.0': {} @@ -18960,7 +19033,7 @@ snapshots: transitivePeerDependencies: - supports-color - babel-loader@8.4.1(@babel/core@7.25.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + babel-loader@8.4.1(@babel/core@7.25.2)(webpack@5.95.0): dependencies: '@babel/core': 7.25.2 find-cache-dir: 3.3.2 @@ -18969,7 +19042,7 @@ snapshots: schema-utils: 2.7.1 webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) - babel-loader@9.2.1(@babel/core@7.25.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + babel-loader@9.2.1(@babel/core@7.25.2)(webpack@5.95.0): dependencies: '@babel/core': 7.25.2 find-cache-dir: 4.0.0 @@ -19122,6 +19195,8 @@ snapshots: base64-js@1.5.1: {} + base64id@2.0.0: {} + basic-auth@2.0.1: dependencies: safe-buffer: 5.1.2 @@ -19676,6 +19751,8 @@ snapshots: cookie@0.6.0: {} + cookie@0.7.2: {} + cookiejar@2.1.4: {} cookies@0.9.1: @@ -19687,7 +19764,7 @@ snapshots: dependencies: is-what: 3.14.1 - copy-webpack-plugin@10.2.4(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + copy-webpack-plugin@10.2.4(webpack@5.95.0): dependencies: fast-glob: 3.3.2 glob-parent: 6.0.2 @@ -19857,7 +19934,7 @@ snapshots: dependencies: utrie: 1.0.2 - css-loader@6.11.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + css-loader@6.11.0(webpack@5.95.0): dependencies: icss-utils: 5.1.0(postcss@8.4.47) postcss: 8.4.47 @@ -19870,7 +19947,7 @@ snapshots: optionalDependencies: webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) - css-loader@7.1.2(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + css-loader@7.1.2(webpack@5.95.0): dependencies: icss-utils: 5.1.0(postcss@8.4.47) postcss: 8.4.47 @@ -19883,7 +19960,7 @@ snapshots: optionalDependencies: webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) - css-minimizer-webpack-plugin@3.4.1(esbuild@0.19.12)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + css-minimizer-webpack-plugin@3.4.1(esbuild@0.19.12)(webpack@5.95.0): dependencies: cssnano: 5.1.15(postcss@8.4.47) jest-worker: 27.5.1 @@ -19895,7 +19972,7 @@ snapshots: optionalDependencies: esbuild: 0.19.12 - css-minimizer-webpack-plugin@5.0.1(esbuild@0.19.12)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + css-minimizer-webpack-plugin@5.0.1(esbuild@0.19.12)(webpack@5.95.0): dependencies: '@jridgewell/trace-mapping': 0.3.25 cssnano: 6.1.2(postcss@8.4.47) @@ -20519,6 +20596,25 @@ snapshots: fast-json-parse: 1.0.3 objectorarray: 1.0.5 + engine.io-parser@5.2.3: {} + + engine.io@6.6.2: + dependencies: + '@types/cookie': 0.4.1 + '@types/cors': 2.8.17 + '@types/node': 18.16.9 + accepts: 1.3.8 + base64id: 2.0.0 + cookie: 0.7.2 + cors: 2.8.5 + debug: 4.3.7 + engine.io-parser: 5.2.3 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + enhanced-resolve@5.17.1: dependencies: graceful-fs: 4.2.11 @@ -21041,7 +21137,7 @@ snapshots: eslint-visitor-keys@3.4.3: {} - eslint-webpack-plugin@3.2.0(eslint@8.57.1)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + eslint-webpack-plugin@3.2.0(eslint@8.57.1)(webpack@5.95.0): dependencies: '@types/eslint': 8.56.12 eslint: 8.57.1 @@ -21343,7 +21439,7 @@ snapshots: dependencies: flat-cache: 3.2.0 - file-loader@6.2.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + file-loader@6.2.0(webpack@5.95.0): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 @@ -21476,7 +21572,7 @@ snapshots: cross-spawn: 7.0.3 signal-exit: 4.1.0 - fork-ts-checker-webpack-plugin@6.5.3(eslint@8.57.1)(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + fork-ts-checker-webpack-plugin@6.5.3(eslint@8.57.1)(typescript@5.6.2)(webpack@5.95.0): dependencies: '@babel/code-frame': 7.24.7 '@types/json-schema': 7.0.15 @@ -21496,7 +21592,7 @@ snapshots: optionalDependencies: eslint: 8.57.1 - fork-ts-checker-webpack-plugin@7.2.13(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + fork-ts-checker-webpack-plugin@7.2.13(typescript@5.6.2)(webpack@5.95.0): dependencies: '@babel/code-frame': 7.24.7 chalk: 4.1.2 @@ -21513,7 +21609,7 @@ snapshots: typescript: 5.6.2 webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) - fork-ts-checker-webpack-plugin@8.0.0(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + fork-ts-checker-webpack-plugin@8.0.0(typescript@5.6.2)(webpack@5.95.0): dependencies: '@babel/code-frame': 7.24.7 chalk: 4.1.2 @@ -21530,7 +21626,7 @@ snapshots: typescript: 5.6.2 webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) - fork-ts-checker-webpack-plugin@9.0.2(typescript@5.3.3)(webpack@5.94.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))): + fork-ts-checker-webpack-plugin@9.0.2(typescript@5.3.3)(webpack@5.94.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): dependencies: '@babel/code-frame': 7.24.7 chalk: 4.1.2 @@ -21545,7 +21641,7 @@ snapshots: semver: 7.6.3 tapable: 2.2.1 typescript: 5.3.3 - webpack: 5.94.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0)) + webpack: 5.94.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) form-data@3.0.2: dependencies: @@ -22129,7 +22225,7 @@ snapshots: html-void-elements@3.0.0: {} - html-webpack-plugin@5.6.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + html-webpack-plugin@5.6.0(webpack@5.95.0): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -23772,7 +23868,7 @@ snapshots: leaflet@1.9.4: {} - less-loader@11.1.0(less@4.1.3)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + less-loader@11.1.0(less@4.1.3)(webpack@5.95.0): dependencies: klona: 2.0.6 less: 4.1.3 @@ -23804,7 +23900,7 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - license-webpack-plugin@4.0.2(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + license-webpack-plugin@4.0.2(webpack@5.95.0): dependencies: webpack-sources: 3.2.3 optionalDependencies: @@ -24726,7 +24822,7 @@ snapshots: min-indent@1.0.1: {} - mini-css-extract-plugin@2.4.7(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + mini-css-extract-plugin@2.4.7(webpack@5.95.0): dependencies: schema-utils: 4.2.0 webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) @@ -24897,7 +24993,7 @@ snapshots: node-machine-id@1.1.12: {} - node-polyfill-webpack-plugin@2.0.1(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + node-polyfill-webpack-plugin@2.0.1(webpack@5.95.0): dependencies: assert: 2.1.0 browserify-zlib: 0.2.0 @@ -25670,7 +25766,7 @@ snapshots: postcss: 8.4.47 ts-node: 10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2) - postcss-loader@6.2.1(postcss@8.4.47)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + postcss-loader@6.2.1(postcss@8.4.47)(webpack@5.95.0): dependencies: cosmiconfig: 7.1.0 klona: 2.0.6 @@ -25678,7 +25774,7 @@ snapshots: semver: 7.6.3 webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) - postcss-loader@8.1.1(postcss@8.4.47)(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + postcss-loader@8.1.1(postcss@8.4.47)(typescript@5.6.2)(webpack@5.95.0): dependencies: cosmiconfig: 9.0.0(typescript@5.6.2) jiti: 1.21.6 @@ -26248,7 +26344,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-dev-utils@12.0.1(eslint@8.57.1)(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + react-dev-utils@12.0.1(eslint@8.57.1)(typescript@5.6.2)(webpack@5.95.0): dependencies: '@babel/code-frame': 7.24.7 address: 1.2.2 @@ -26259,7 +26355,7 @@ snapshots: escape-string-regexp: 4.0.0 filesize: 8.0.7 find-up: 5.0.0 - fork-ts-checker-webpack-plugin: 6.5.3(eslint@8.57.1)(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + fork-ts-checker-webpack-plugin: 6.5.3(eslint@8.57.1)(typescript@5.6.2)(webpack@5.95.0) global-modules: 2.0.0 globby: 11.1.0 gzip-size: 6.0.0 @@ -26410,56 +26506,56 @@ snapshots: tiny-invariant: 1.3.3 tiny-warning: 1.0.3 - react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/babel__core@7.20.5)(esbuild@0.19.12)(eslint@8.57.1)(react@18.3.1)(sass@1.79.3)(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack-hot-middleware@2.26.1): + react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/babel__core@7.20.5)(esbuild@0.19.12)(eslint@8.57.1)(react@18.3.1)(sass@1.79.3)(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2))(type-fest@2.19.0)(typescript@5.6.2)(webpack-cli@5.1.4)(webpack-hot-middleware@2.26.1): dependencies: '@babel/core': 7.25.2 - '@pmmmwh/react-refresh-webpack-plugin': 0.5.15(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(webpack-hot-middleware@2.26.1)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + '@pmmmwh/react-refresh-webpack-plugin': 0.5.15(react-refresh@0.11.0)(type-fest@2.19.0)(webpack-dev-server@4.15.2)(webpack-hot-middleware@2.26.1)(webpack@5.95.0) '@svgr/webpack': 5.5.0 babel-jest: 27.5.1(@babel/core@7.25.2) - babel-loader: 8.4.1(@babel/core@7.25.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + babel-loader: 8.4.1(@babel/core@7.25.2)(webpack@5.95.0) babel-plugin-named-asset-import: 0.3.8(@babel/core@7.25.2) babel-preset-react-app: 10.0.1 bfj: 7.1.0 browserslist: 4.24.0 camelcase: 6.3.0 case-sensitive-paths-webpack-plugin: 2.4.0 - css-loader: 6.11.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - css-minimizer-webpack-plugin: 3.4.1(esbuild@0.19.12)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + css-loader: 6.11.0(webpack@5.95.0) + css-minimizer-webpack-plugin: 3.4.1(esbuild@0.19.12)(webpack@5.95.0) dotenv: 10.0.0 dotenv-expand: 5.1.0 eslint: 8.57.1 eslint-config-react-app: 7.0.1(@babel/plugin-syntax-flow@7.24.7(@babel/core@7.25.2))(@babel/plugin-transform-react-jsx@7.25.2(@babel/core@7.25.2))(eslint@8.57.1)(jest@27.5.1(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2)))(typescript@5.6.2) - eslint-webpack-plugin: 3.2.0(eslint@8.57.1)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - file-loader: 6.2.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + eslint-webpack-plugin: 3.2.0(eslint@8.57.1)(webpack@5.95.0) + file-loader: 6.2.0(webpack@5.95.0) fs-extra: 10.1.0 - html-webpack-plugin: 5.6.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + html-webpack-plugin: 5.6.0(webpack@5.95.0) identity-obj-proxy: 3.0.0 jest: 27.5.1(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2)) jest-resolve: 27.5.1 jest-watch-typeahead: 1.1.0(jest@27.5.1(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2))) - mini-css-extract-plugin: 2.4.7(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + mini-css-extract-plugin: 2.4.7(webpack@5.95.0) postcss: 8.4.47 postcss-flexbugs-fixes: 5.0.2(postcss@8.4.47) - postcss-loader: 6.2.1(postcss@8.4.47)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + postcss-loader: 6.2.1(postcss@8.4.47)(webpack@5.95.0) postcss-normalize: 10.0.1(browserslist@4.24.0)(postcss@8.4.47) postcss-preset-env: 7.8.3(postcss@8.4.47) prompts: 2.4.2 react: 18.3.1 react-app-polyfill: 3.0.0 - react-dev-utils: 12.0.1(eslint@8.57.1)(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + react-dev-utils: 12.0.1(eslint@8.57.1)(typescript@5.6.2)(webpack@5.95.0) react-refresh: 0.11.0 resolve: 1.22.8 resolve-url-loader: 4.0.0 - sass-loader: 12.6.0(sass@1.79.3)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + sass-loader: 12.6.0(sass@1.79.3)(webpack@5.95.0) semver: 7.6.3 - source-map-loader: 3.0.2(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - style-loader: 3.3.4(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + source-map-loader: 3.0.2(webpack@5.95.0) + style-loader: 3.3.4(webpack@5.95.0) tailwindcss: 3.4.13(ts-node@10.9.1(@swc/core@1.5.29(@swc/helpers@0.5.13))(@types/node@18.16.9)(typescript@5.6.2)) - terser-webpack-plugin: 5.3.10(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + terser-webpack-plugin: 5.3.10(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack@5.95.0) webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) - webpack-dev-server: 4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - webpack-manifest-plugin: 4.1.1(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - workbox-webpack-plugin: 6.6.0(@types/babel__core@7.20.5)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + webpack-dev-server: 4.15.2(webpack-cli@5.1.4)(webpack@5.95.0) + webpack-manifest-plugin: 4.1.1(webpack@5.95.0) + workbox-webpack-plugin: 6.6.0(@types/babel__core@7.20.5)(webpack@5.95.0) optionalDependencies: fsevents: 2.3.3 typescript: 5.6.2 @@ -26938,7 +27034,7 @@ snapshots: sanitize.css@13.0.0: {} - sass-loader@12.6.0(sass@1.79.3)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + sass-loader@12.6.0(sass@1.79.3)(webpack@5.95.0): dependencies: klona: 2.0.6 neo-async: 2.6.2 @@ -26946,7 +27042,7 @@ snapshots: optionalDependencies: sass: 1.79.3 - sass-loader@13.3.3(sass@1.79.3)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + sass-loader@13.3.3(sass@1.79.3)(webpack@5.95.0): dependencies: neo-async: 2.6.2 webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) @@ -27186,6 +27282,36 @@ snapshots: dot-case: 3.0.4 tslib: 2.7.0 + socket.io-adapter@2.5.5: + dependencies: + debug: 4.3.7 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + socket.io-parser@4.2.4: + dependencies: + '@socket.io/component-emitter': 3.1.2 + debug: 4.3.7 + transitivePeerDependencies: + - supports-color + + socket.io@4.8.0: + dependencies: + accepts: 1.3.8 + base64id: 2.0.0 + cors: 2.8.5 + debug: 4.3.7 + engine.io: 6.6.2 + socket.io-adapter: 2.5.5 + socket.io-parser: 4.2.4 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + sockjs@0.3.24: dependencies: faye-websocket: 0.11.4 @@ -27206,14 +27332,14 @@ snapshots: source-map-js@1.2.1: {} - source-map-loader@3.0.2(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + source-map-loader@3.0.2(webpack@5.95.0): dependencies: abab: 2.0.6 iconv-lite: 0.6.3 source-map-js: 1.2.1 webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) - source-map-loader@5.0.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + source-map-loader@5.0.0(webpack@5.95.0): dependencies: iconv-lite: 0.6.3 source-map-js: 1.2.1 @@ -27470,11 +27596,11 @@ snapshots: '@tokenizer/token': 0.3.0 peek-readable: 5.2.0 - style-loader@3.3.4(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + style-loader@3.3.4(webpack@5.95.0): dependencies: webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) - style-loader@4.0.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + style-loader@4.0.0(webpack@5.95.0): dependencies: webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) @@ -27516,7 +27642,7 @@ snapshots: stylis@4.2.0: {} - stylus-loader@7.1.3(stylus@0.59.0)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + stylus-loader@7.1.3(stylus@0.59.0)(webpack@5.95.0): dependencies: fast-glob: 3.3.2 normalize-path: 3.0.0 @@ -27716,19 +27842,19 @@ snapshots: ansi-escapes: 4.3.2 supports-hyperlinks: 2.3.0 - terser-webpack-plugin@5.3.10(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack@5.94.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))): + terser-webpack-plugin@5.3.10(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack@5.94.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 terser: 5.33.0 - webpack: 5.94.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0)) + webpack: 5.94.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) optionalDependencies: '@swc/core': 1.5.29(@swc/helpers@0.5.13) esbuild: 0.19.12 - terser-webpack-plugin@5.3.10(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + terser-webpack-plugin@5.3.10(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack@5.95.0): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 @@ -27876,7 +28002,7 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-loader@9.5.1(typescript@5.6.2)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + ts-loader@9.5.1(typescript@5.6.2)(webpack@5.95.0): dependencies: chalk: 4.1.2 enhanced-resolve: 5.17.1 @@ -28442,9 +28568,9 @@ snapshots: webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0): dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack-dev-server@4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.95.0) + '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.95.0) + '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack-dev-server@4.15.2)(webpack@5.95.0) colorette: 2.0.20 commander: 10.0.1 cross-spawn: 7.0.3 @@ -28456,9 +28582,9 @@ snapshots: webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) webpack-merge: 5.10.0 optionalDependencies: - webpack-dev-server: 4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + webpack-dev-server: 4.15.2(webpack-cli@5.1.4)(webpack@5.95.0) - webpack-dev-middleware@5.3.4(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + webpack-dev-middleware@5.3.4(webpack@5.95.0): dependencies: colorette: 2.0.20 memfs: 3.5.3 @@ -28467,7 +28593,7 @@ snapshots: schema-utils: 4.2.0 webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) - webpack-dev-middleware@6.1.3(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + webpack-dev-middleware@6.1.3(webpack@5.95.0): dependencies: colorette: 2.0.20 memfs: 3.5.3 @@ -28477,7 +28603,7 @@ snapshots: optionalDependencies: webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) - webpack-dev-middleware@7.4.2(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + webpack-dev-middleware@7.4.2(webpack@5.95.0): dependencies: colorette: 2.0.20 memfs: 4.14.0 @@ -28488,7 +28614,7 @@ snapshots: optionalDependencies: webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) - webpack-dev-server@4.15.2(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + webpack-dev-server@4.15.2(webpack-cli@5.1.4)(webpack@5.95.0): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -28518,7 +28644,7 @@ snapshots: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 5.3.4(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + webpack-dev-middleware: 5.3.4(webpack@5.95.0) ws: 8.18.0 optionalDependencies: webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) @@ -28529,7 +28655,7 @@ snapshots: - supports-color - utf-8-validate - webpack-dev-server@5.1.0(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + webpack-dev-server@5.1.0(webpack-cli@5.1.4)(webpack@5.95.0): dependencies: '@types/bonjour': 3.5.13 '@types/connect-history-api-fallback': 1.5.4 @@ -28557,7 +28683,7 @@ snapshots: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 7.4.2(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + webpack-dev-middleware: 7.4.2(webpack@5.95.0) ws: 8.18.0 optionalDependencies: webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) @@ -28574,7 +28700,7 @@ snapshots: html-entities: 2.5.2 strip-ansi: 6.0.1 - webpack-manifest-plugin@4.1.1(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + webpack-manifest-plugin@4.1.1(webpack@5.95.0): dependencies: tapable: 2.2.1 webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) @@ -28600,16 +28726,16 @@ snapshots: webpack-sources@3.2.3: {} - webpack-subresource-integrity@5.1.0(html-webpack-plugin@5.6.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)))(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + webpack-subresource-integrity@5.1.0(html-webpack-plugin@5.6.0(webpack@5.95.0))(webpack@5.95.0): dependencies: typed-assert: 1.0.9 webpack: 5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4) optionalDependencies: - html-webpack-plugin: 5.6.0(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + html-webpack-plugin: 5.6.0(webpack@5.95.0) webpack-virtual-modules@0.6.2: {} - webpack@5.94.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0)): + webpack@5.94.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4): dependencies: '@types/estree': 1.0.6 '@webassemblyjs/ast': 1.12.1 @@ -28631,7 +28757,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack@5.94.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4(webpack-dev-server@4.15.2)(webpack@5.95.0))) + terser-webpack-plugin: 5.3.10(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack@5.94.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) watchpack: 2.4.2 webpack-sources: 3.2.3 optionalDependencies: @@ -28663,7 +28789,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)) + terser-webpack-plugin: 5.3.10(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack@5.95.0) watchpack: 2.4.2 webpack-sources: 3.2.3 optionalDependencies: @@ -28884,7 +29010,7 @@ snapshots: workbox-sw@6.6.0: {} - workbox-webpack-plugin@6.6.0(@types/babel__core@7.20.5)(webpack@5.95.0(@swc/core@1.5.29(@swc/helpers@0.5.13))(esbuild@0.19.12)(webpack-cli@5.1.4)): + workbox-webpack-plugin@6.6.0(@types/babel__core@7.20.5)(webpack@5.95.0): dependencies: fast-json-stable-stringify: 2.1.0 pretty-bytes: 5.6.0 From e81f1ccb9bccb2bcc91fa486f294de506838dbc8 Mon Sep 17 00:00:00 2001 From: Amandine Jacquelin Date: Wed, 23 Oct 2024 16:01:40 +0200 Subject: [PATCH 22/22] =?UTF-8?q?Met=20=C3=A0=20jour=20le=20code=20avec=20?= =?UTF-8?q?le=20.editconfig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../auth/decorators/token-info.decorators.ts | 2 +- backend/src/auth/guards/auth.guard.ts | 1 + .../models/private-utilisateur-droit.table.ts | 2 +- .../src/auth/models/supabase-jwt.models.ts | 3 +- .../src/auth/services/auth.service.spec.ts | 28 +-- backend/src/auth/services/auth.service.ts | 41 ++-- backend/src/brevo/service/brevo.service.ts | 15 +- .../collectivite-banatic-competence.table.ts | 2 +- .../models/collectivite-test.table.ts | 2 +- .../models/collectivite.request.ts | 5 +- .../src/collectivites/models/epci.table.ts | 8 +- .../models/groupement-collectivite.table.ts | 2 +- .../services/collectivites.service.ts | 12 +- .../services/groupements.service.ts | 6 +- .../common/controllers/version.controller.ts | 1 + .../src/common/models/count-synthese.dto.ts | 5 +- .../src/common/models/modified-since.enum.ts | 2 +- backend/src/common/models/version.models.ts | 3 +- backend/src/common/services/gcloud.helper.ts | 4 +- backend/src/config/configuration.model.ts | 7 +- .../src/directus/models/directus.models.ts | 1 - .../src/directus/service/directus.service.ts | 6 +- .../src/documents/models/document-lien.dto.ts | 4 +- .../documents/models/document.basetable.ts | 2 - .../preuve-reglementaire-definition.table.ts | 2 +- .../documents/services/document.service.ts | 4 +- .../controllers/fiches-action.controller.ts | 1 + .../action-impact-fiche-action.table.ts | 4 +- .../models/fiche-action-action.table.ts | 9 +- .../fiches/models/fiche-action-axe.table.ts | 2 +- .../fiche-action-effet-attendu.table.ts | 4 +- .../fiche-action-financeur-tag.table.ts | 4 +- .../models/fiche-action-indicateur.table.ts | 4 +- .../fiches/models/fiche-action-lien.table.ts | 2 +- .../fiche-action-partenaire-tag.table.ts | 4 +- .../models/fiche-action-pilote.table.ts | 6 +- .../models/fiche-action-referent.table.ts | 4 +- .../models/fiche-action-service-tag.table.ts | 4 +- .../models/fiche-action-service.table.ts | 4 +- .../fiche-action-sous-thematique.table.ts | 4 +- .../fiche-action-structure-tag.table.ts | 4 +- .../models/fiche-action-thematique.table.ts | 2 +- .../get-fiches-action-synthese.response.ts | 3 +- .../get-fiches-actions-filter.request.ts | 2 +- .../plan-action-type-categorie.table.ts | 2 +- .../models/plan-action-type-category.table.ts | 2 +- .../fiches/models/plan-action-type.table.ts | 4 +- backend/src/fiches/services/axe.service.ts | 10 +- backend/src/fiches/services/fiche.service.ts | 10 +- .../fiches-action-synthese.service.ts | 42 ++-- .../controllers/indicateurs.controller.ts | 12 +- .../controllers/trajectoires.controller.ts | 42 ++-- .../models/calcultrajectoire.models.ts | 18 +- .../models/deleteIndicateurs.models.ts | 4 +- .../models/getIndicateurs.models.ts | 4 +- .../models/indicateur-definition.table.ts | 17 +- .../indicateur-source-metadonnee.table.ts | 6 +- .../models/indicateur-valeur.table.ts | 24 ++- .../models/upsertIndicateurs.models.ts | 8 +- .../routers/trajectoires.router.ts | 6 +- .../services/indicateurSources.service.ts | 14 +- .../services/indicateurs.service.spec.ts | 62 +++--- .../services/indicateurs.service.ts | 181 ++++++++++-------- .../services/trajectoires-data.service.ts | 81 ++++---- .../trajectoires-spreadsheet.service.ts | 9 +- .../services/trajectoires-xlsx.service.ts | 48 ++--- backend/src/main.ts | 1 + .../controllers/action-impact.controllers.ts | 4 +- .../panier/controllers/panier.controllers.ts | 40 ++-- .../models/action-impact-action.table.ts | 2 +- .../action-impact-banatic-competence.table.ts | 2 +- .../action-impact-cateorie-fnv.table.ts | 2 +- .../action-impact-effet-attendu.table.ts | 2 +- ...tion-impact-fourchette-budgetaire.table.ts | 2 +- .../models/action-impact-indicateur.table.ts | 2 +- .../models/action-impact-panier.table.ts | 2 +- .../models/action-impact-partenaire.table.ts | 2 +- .../action-impact-sous-thematique.table.ts | 2 +- .../models/action-impact-statut.table.ts | 12 +- ...on-impact-temps-de-mise-en-oeuvre.table.ts | 2 +- .../models/action-impact-thematique.table.ts | 2 +- .../src/panier/models/action-impact.table.ts | 12 +- .../models/action-in-panier-statut.request.ts | 20 +- .../panier/models/action-in-panier.request.ts | 4 +- .../models/create-plan-from-panier.request.ts | 6 +- .../models/get-panier-complet.request.ts | 6 +- .../models/get-panier-complet.response.ts | 4 +- backend/src/panier/models/panier.table.ts | 4 +- .../panier/services/action-impact.service.ts | 48 ++--- backend/src/panier/services/panier.service.ts | 160 ++++++++-------- .../services/plan-from-panier.service.ts | 177 ++++++++--------- .../models/action-definition.table.ts | 8 +- .../models/action-relation.table.ts | 2 +- .../spreadsheets/services/sheet.service.ts | 1 + .../taxonomie/models/categorie-tag.table.ts | 8 +- .../taxonomie/models/financeur-tag.table.ts | 2 +- .../taxonomie/models/partenaire-tag.table.ts | 4 +- .../taxonomie/models/personne-tag.table.ts | 2 +- .../src/taxonomie/models/service-tag.table.ts | 2 +- .../taxonomie/models/sous-thematique.table.ts | 4 +- .../taxonomie/models/structure-tag.table.ts | 2 +- .../services/panier-partenaire.service.ts | 2 +- backend/src/taxonomie/services/tag.service.ts | 4 +- backend/src/trpc.router.ts | 4 +- 104 files changed, 722 insertions(+), 686 deletions(-) diff --git a/backend/src/auth/decorators/token-info.decorators.ts b/backend/src/auth/decorators/token-info.decorators.ts index 2be0de91c6..dab9d416cf 100644 --- a/backend/src/auth/decorators/token-info.decorators.ts +++ b/backend/src/auth/decorators/token-info.decorators.ts @@ -4,5 +4,5 @@ export const TokenInfo = createParamDecorator( (data: unknown, ctx: ExecutionContext) => { const request = ctx.switchToHttp().getRequest(); return request.tokenInfo; - }, + } ); diff --git a/backend/src/auth/guards/auth.guard.ts b/backend/src/auth/guards/auth.guard.ts index 51ee94ce51..fa5828f8b9 100644 --- a/backend/src/auth/guards/auth.guard.ts +++ b/backend/src/auth/guards/auth.guard.ts @@ -16,6 +16,7 @@ import { SupabaseJwtPayload } from '../models/supabase-jwt.models'; @Injectable() export class AuthGuard implements CanActivate { private readonly logger = new Logger(AuthGuard.name); + constructor( private jwtService: JwtService, private reflector: Reflector, diff --git a/backend/src/auth/models/private-utilisateur-droit.table.ts b/backend/src/auth/models/private-utilisateur-droit.table.ts index 1184bc1edb..0dcd6c2e6d 100644 --- a/backend/src/auth/models/private-utilisateur-droit.table.ts +++ b/backend/src/auth/models/private-utilisateur-droit.table.ts @@ -34,7 +34,7 @@ export const utilisateurDroitTable = pgTable('private_utilisateur_droit', { .default(sql.raw(`CURRENT_TIMESTAMP`)) .notNull(), modifiedAt: timestamp('modified_at', { withTimezone: true }).default( - sql.raw(`CURRENT_TIMESTAMP`), + sql.raw(`CURRENT_TIMESTAMP`) ), active: boolean('active').notNull(), niveauAcces: niveauAccessEnum('niveau_acces') diff --git a/backend/src/auth/models/supabase-jwt.models.ts b/backend/src/auth/models/supabase-jwt.models.ts index 44054a5b75..f0fdb7f5c7 100644 --- a/backend/src/auth/models/supabase-jwt.models.ts +++ b/backend/src/auth/models/supabase-jwt.models.ts @@ -5,6 +5,7 @@ export enum SupabaseRole { SERVICE_ROLE = 'service_role', ANON = 'anon', // Anonymous } + export interface SupabaseJwtPayload extends jwt.JwtPayload { email?: string; phone?: string; @@ -15,4 +16,4 @@ export interface SupabaseJwtPayload extends jwt.JwtPayload { session_id: string; role: SupabaseRole; is_anonymous: boolean; -} \ No newline at end of file +} diff --git a/backend/src/auth/services/auth.service.spec.ts b/backend/src/auth/services/auth.service.spec.ts index 2255836923..4da99c47f6 100644 --- a/backend/src/auth/services/auth.service.spec.ts +++ b/backend/src/auth/services/auth.service.spec.ts @@ -32,8 +32,8 @@ describe('AuthService', () => { SupabaseRole.AUTHENTICATED, [], [1], - NiveauAcces.LECTURE, - ), + NiveauAcces.LECTURE + ) ).toBe(false); }); @@ -43,8 +43,8 @@ describe('AuthService', () => { SupabaseRole.ANON, [], [], - NiveauAcces.LECTURE, - ), + NiveauAcces.LECTURE + ) ).toBe(false); }); @@ -54,8 +54,8 @@ describe('AuthService', () => { SupabaseRole.SERVICE_ROLE, [], [1, 2, 3], - NiveauAcces.ADMIN, - ), + NiveauAcces.ADMIN + ) ).toBe(true); }); @@ -88,8 +88,8 @@ describe('AuthService', () => { SupabaseRole.AUTHENTICATED, droits, [1, 2], - NiveauAcces.EDITION, - ), + NiveauAcces.EDITION + ) ).toBe(true); }); @@ -122,8 +122,8 @@ describe('AuthService', () => { SupabaseRole.AUTHENTICATED, droits, [1, 2], - NiveauAcces.EDITION, - ), + NiveauAcces.EDITION + ) ).toBe(false); }); @@ -156,8 +156,8 @@ describe('AuthService', () => { SupabaseRole.AUTHENTICATED, droits, [1, 2], - NiveauAcces.EDITION, - ), + NiveauAcces.EDITION + ) ).toBe(false); }); @@ -180,8 +180,8 @@ describe('AuthService', () => { SupabaseRole.AUTHENTICATED, droits, [1, 2], - NiveauAcces.EDITION, - ), + NiveauAcces.EDITION + ) ).toBe(false); }); }); diff --git a/backend/src/auth/services/auth.service.ts b/backend/src/auth/services/auth.service.ts index da58807d08..1b29886547 100644 --- a/backend/src/auth/services/auth.service.ts +++ b/backend/src/auth/services/auth.service.ts @@ -24,18 +24,18 @@ export class AuthService { constructor( private readonly databaseService: DatabaseService, - private readonly collectiviteService: CollectivitesService, + private readonly collectiviteService: CollectivitesService ) {} aDroitsSuffisants( tokenRole: SupabaseRole, droits: UtilisateurDroitType[], collectiviteIds: number[], - niveauAccessMinimum: NiveauAcces, + niveauAccessMinimum: NiveauAcces ): boolean { if (tokenRole === SupabaseRole.SERVICE_ROLE) { this.logger.log( - `Rôle de service détecté, accès autorisé à toutes les collectivités`, + `Rôle de service détecté, accès autorisé à toutes les collectivités` ); return true; } else if (tokenRole === SupabaseRole.AUTHENTICATED) { @@ -45,28 +45,28 @@ export class AuthService { for (const collectiviteId of collectiviteIds) { const droit = droits.find( (droit) => - droit.collectiviteId.toString() === collectiviteId.toString(), // Etrangement collectiviteId est un string + droit.collectiviteId.toString() === collectiviteId.toString() // Etrangement collectiviteId est un string ); if (!droit) { this.logger.log( - `Droit introuvable pour la collectivité ${collectiviteId}`, + `Droit introuvable pour la collectivité ${collectiviteId}` ); return false; } if (!droit.active) { this.logger.log( - `Droit inactif pour la collectivité ${collectiviteId} et l'utilisateur ${droit.userId}`, + `Droit inactif pour la collectivité ${collectiviteId} et l'utilisateur ${droit.userId}` ); return false; } const droitNiveauAccessIndex = niveauAccessOrdonne.indexOf( - droit.niveauAcces, + droit.niveauAcces ); if (droitNiveauAccessIndex < niveauAccessMinimumIndex) { this.logger.log( - `Niveau d'accès insuffisant pour la collectivité ${collectiviteId} et l'utilisateur ${droit.userId} (niveau d'accès: ${droit.niveauAcces}, demandé: ${niveauAccessMinimum})`, + `Niveau d'accès insuffisant pour la collectivité ${collectiviteId} et l'utilisateur ${droit.userId} (niveau d'accès: ${droit.niveauAcces}, demandé: ${niveauAccessMinimum})` ); return false; } @@ -78,17 +78,19 @@ export class AuthService { async getDroitsUtilisateur( userId: string, - collectiviteIds?: number[], + collectiviteIds?: number[] ): Promise { this.logger.log( - `Récupération des droits de l'utilisateur ${userId} et les collectivités ${collectiviteIds?.join(', ')}`, + `Récupération des droits de l'utilisateur ${userId} et les collectivités ${collectiviteIds?.join( + ', ' + )}` ); const conditions: (SQLWrapper | SQL)[] = [ eq(utilisateurDroitTable.userId, userId), ]; if (collectiviteIds?.length) { conditions.push( - inArray(utilisateurDroitTable.collectiviteId, collectiviteIds), + inArray(utilisateurDroitTable.collectiviteId, collectiviteIds) ); } const droits = await this.databaseService.db @@ -103,7 +105,7 @@ export class AuthService { tokenInfo: SupabaseJwtPayload, collectiviteIds: number[], niveauAccessMinimum: NiveauAcces, - doNotThrow?: boolean, + doNotThrow?: boolean ): Promise { let droits: UtilisateurDroitType[] = []; const userId = tokenInfo?.sub; @@ -114,7 +116,7 @@ export class AuthService { tokenInfo?.role, droits, collectiviteIds, - niveauAccessMinimum, + niveauAccessMinimum ); if (!authorise && !doNotThrow) { throw new UnauthorizedException(`Droits insuffisants`); @@ -166,17 +168,18 @@ export class AuthService { async verifieAccesRestreintCollectivite( tokenInfo: SupabaseJwtPayload, collectiviteId: number, - doNotThrow?: boolean, + doNotThrow?: boolean ): Promise { if (tokenInfo.role === SupabaseRole.SERVICE_ROLE) { this.logger.log( - `Rôle de service détecté, accès autorisé à toutes les collectivités`, + `Rôle de service détecté, accès autorisé à toutes les collectivités` ); return true; } else if (tokenInfo.role === SupabaseRole.AUTHENTICATED) { let authorise = false; - const collectivite = - await this.collectiviteService.getCollectivite(collectiviteId); + const collectivite = await this.collectiviteService.getCollectivite( + collectiviteId + ); if (collectivite.collectivite.accessRestreint) { // Si la collectivité est en accès restreint, l'utilisateur doit : // avoir un droit en lecture sur la collectivité, ou avoir un rôle support, @@ -186,7 +189,7 @@ export class AuthService { tokenInfo, [collectiviteId], NiveauAcces.LECTURE, - doNotThrow, + doNotThrow )) || (await this.estSupport(tokenInfo)); // TODO || private.est_auditeur(collectivite_id) } else { // Si la collectivité n'est pas en accès restreint, l'utilisateur doit : @@ -197,7 +200,7 @@ export class AuthService { tokenInfo, [collectiviteId], NiveauAcces.LECTURE, - doNotThrow, + doNotThrow )); } if (!authorise && !doNotThrow) { diff --git a/backend/src/brevo/service/brevo.service.ts b/backend/src/brevo/service/brevo.service.ts index d6c8ac981d..57723ac0b0 100644 --- a/backend/src/brevo/service/brevo.service.ts +++ b/backend/src/brevo/service/brevo.service.ts @@ -6,12 +6,9 @@ import ConfigurationService from '../../config/configuration.service'; export default class BrevoService { private readonly logger = new Logger(BrevoService.name); - constructor( - private readonly configurationService: ConfigurationService, - ) {} + constructor(private readonly configurationService: ConfigurationService) {} - private readonly brevoKey = - this.configurationService.get('BREVO_API_KEY'); + private readonly brevoKey = this.configurationService.get('BREVO_API_KEY'); private readonly headers = { Accept: 'application/json', 'Api-key': `${this.brevoKey}`, @@ -54,7 +51,7 @@ export default class BrevoService { method: 'POST', headers: this.headers, body: JSON.stringify({ emails: emails }), - }, + } ); if (!response.ok) { console.log( @@ -62,7 +59,7 @@ export default class BrevoService { emails + " n'ont pas pu être ajouté à la liste #" + list + - '.', + '.' ); return null; } @@ -108,7 +105,7 @@ export default class BrevoService { method: 'POST', headers: this.headers, body: JSON.stringify({ emails: emails }), - }, + } ); if (!response.ok) { console.log( @@ -116,7 +113,7 @@ export default class BrevoService { emails + " n'ont pas pu être enlevé de la liste #" + list + - '.', + '.' ); return null; } diff --git a/backend/src/collectivites/models/collectivite-banatic-competence.table.ts b/backend/src/collectivites/models/collectivite-banatic-competence.table.ts index 0ceb9dceba..9557f6e101 100644 --- a/backend/src/collectivites/models/collectivite-banatic-competence.table.ts +++ b/backend/src/collectivites/models/collectivite-banatic-competence.table.ts @@ -20,5 +20,5 @@ export const collectiviteBanaticCompetenceTable = pgTable( name: 'collectivite_banatic_competence_pkey', }), }; - }, + } ); diff --git a/backend/src/collectivites/models/collectivite-test.table.ts b/backend/src/collectivites/models/collectivite-test.table.ts index c403a2bff5..60a4493c4e 100644 --- a/backend/src/collectivites/models/collectivite-test.table.ts +++ b/backend/src/collectivites/models/collectivite-test.table.ts @@ -4,7 +4,7 @@ import { collectiviteTable } from './collectivite.table'; export const collectiviteTestTable = pgTable('collectivite_test', { id: serial('id').primaryKey().notNull(), collectiviteId: integer('collectivite_id').references( - () => collectiviteTable.id, + () => collectiviteTable.id ), nom: varchar('nom', { length: 300 }).notNull(), }); diff --git a/backend/src/collectivites/models/collectivite.request.ts b/backend/src/collectivites/models/collectivite.request.ts index 47b7749772..dbc41fd0d9 100644 --- a/backend/src/collectivites/models/collectivite.request.ts +++ b/backend/src/collectivites/models/collectivite.request.ts @@ -1,6 +1,7 @@ import { createZodDto } from '@anatine/zod-nestjs'; import { extendApi, extendZodWithOpenApi } from '@anatine/zod-openapi'; import { z } from 'zod'; + extendZodWithOpenApi(z); export const collectiviteRequestSchema = extendApi( @@ -8,10 +9,10 @@ export const collectiviteRequestSchema = extendApi( collectivite_id: z.coerce.number().int().openapi({ description: 'Identifiant de la collectivité', }), - }), + }) ); export type CollectiviteRequestType = z.infer; export class CollectiviteRequestClass extends createZodDto( - collectiviteRequestSchema, + collectiviteRequestSchema ) {} diff --git a/backend/src/collectivites/models/epci.table.ts b/backend/src/collectivites/models/epci.table.ts index 68b5628acb..c83d977ffc 100644 --- a/backend/src/collectivites/models/epci.table.ts +++ b/backend/src/collectivites/models/epci.table.ts @@ -1,11 +1,5 @@ import { InferInsertModel, InferSelectModel } from 'drizzle-orm'; -import { - integer, - pgEnum, - pgTable, - serial, - varchar, -} from 'drizzle-orm/pg-core'; +import { integer, pgEnum, pgTable, serial, varchar } from 'drizzle-orm/pg-core'; import { createInsertSchema, createSelectSchema } from 'drizzle-zod'; import { collectiviteTable } from './collectivite.table'; diff --git a/backend/src/collectivites/models/groupement-collectivite.table.ts b/backend/src/collectivites/models/groupement-collectivite.table.ts index 68149b4426..ba8d6d90d4 100644 --- a/backend/src/collectivites/models/groupement-collectivite.table.ts +++ b/backend/src/collectivites/models/groupement-collectivite.table.ts @@ -11,7 +11,7 @@ export const groupementCollectiviteTable = pgTable('groupement_collectivite', { () => collectiviteTable.id, { onDelete: 'cascade', - }, + } ), }); export type GroupementCollectiviteType = InferSelectModel< diff --git a/backend/src/collectivites/services/collectivites.service.ts b/backend/src/collectivites/services/collectivites.service.ts index 4e494486d4..f123449043 100644 --- a/backend/src/collectivites/services/collectivites.service.ts +++ b/backend/src/collectivites/services/collectivites.service.ts @@ -15,32 +15,32 @@ export default class CollectivitesService { async getCollectivite(collectiviteId: number) { this.logger.log( - `Récupération de la collectivite avec l'identifiant ${collectiviteId}`, + `Récupération de la collectivite avec l'identifiant ${collectiviteId}` ); const collectiviteByIdResult = await this.databaseService.db .select() .from(collectiviteTable) .leftJoin( communeTable, - eq(communeTable.collectiviteId, collectiviteTable.id), + eq(communeTable.collectiviteId, collectiviteTable.id) ) .leftJoin(epciTable, eq(epciTable.collectiviteId, collectiviteTable.id)) .where(eq(collectiviteTable.id, collectiviteId)); if (!collectiviteByIdResult?.length) { throw new NotFoundException( - `Commune avec l'identifiant de collectivite ${collectiviteId} introuvable`, + `Commune avec l'identifiant de collectivite ${collectiviteId} introuvable` ); } this.logger.log( - `Commune trouvé avec l'id ${collectiviteByIdResult[0].collectivite.id}`, + `Commune trouvé avec l'id ${collectiviteByIdResult[0].collectivite.id}` ); return collectiviteByIdResult[0]; } async getEpciByCollectiviteId(collectiviteId: number) { this.logger.log( - `Récupération de l'epci avec l'identifiant ${collectiviteId}`, + `Récupération de l'epci avec l'identifiant ${collectiviteId}` ); const epciByIdResult = await this.databaseService.db .select() @@ -48,7 +48,7 @@ export default class CollectivitesService { .where(eq(epciTable.collectiviteId, collectiviteId)); if (!epciByIdResult?.length) { throw new NotFoundException( - `EPCI avec l'identifiant de collectivite ${collectiviteId} introuvable`, + `EPCI avec l'identifiant de collectivite ${collectiviteId} introuvable` ); } diff --git a/backend/src/collectivites/services/groupements.service.ts b/backend/src/collectivites/services/groupements.service.ts index 79935ccda0..2a51797fd1 100644 --- a/backend/src/collectivites/services/groupements.service.ts +++ b/backend/src/collectivites/services/groupements.service.ts @@ -32,7 +32,7 @@ export default class GroupementsService { if (groupementResult.length > 1) { throw new HttpException( `Plusieurs groupements trouvés avec le nom ${nom}`, - HttpStatus.INTERNAL_SERVER_ERROR, + HttpStatus.INTERNAL_SERVER_ERROR ); } @@ -42,10 +42,10 @@ export default class GroupementsService { async ajouteCollectiviteAuGroupement( groupementId: number, - collectiviteId: number, + collectiviteId: number ) { this.logger.log( - `Ajout de la collectivite ${collectiviteId} au groupement ${groupementId}`, + `Ajout de la collectivite ${collectiviteId} au groupement ${groupementId}` ); const createGroupementCollectivite: CreateGroupementCollectiviteType = { collectiviteId: collectiviteId, diff --git a/backend/src/common/controllers/version.controller.ts b/backend/src/common/controllers/version.controller.ts index 93d8dad81e..2d0822b9db 100644 --- a/backend/src/common/controllers/version.controller.ts +++ b/backend/src/common/controllers/version.controller.ts @@ -9,6 +9,7 @@ import { versionResponseSchema } from '../models/version.models'; */ @ApiTags('Application') export class VersionResponseClass extends createZodDto(versionResponseSchema) {} + @Controller() export class VersionController { @PublicEndpoint() diff --git a/backend/src/common/models/count-synthese.dto.ts b/backend/src/common/models/count-synthese.dto.ts index a2a5734dd7..7eff1063fc 100644 --- a/backend/src/common/models/count-synthese.dto.ts +++ b/backend/src/common/models/count-synthese.dto.ts @@ -1,16 +1,17 @@ import { extendApi, extendZodWithOpenApi } from '@anatine/zod-openapi'; import { z } from 'zod'; + extendZodWithOpenApi(z); export const countSyntheseValeurSchema = extendApi( z.object({ count: z.number().int(), valeur: z.union([z.string(), z.number(), z.boolean(), z.null()]), - }), + }) ); export type CountSyntheseValeurType = z.infer; export const countSyntheseSchema = extendApi( - z.record(z.string(), countSyntheseValeurSchema), + z.record(z.string(), countSyntheseValeurSchema) ); export type CountSyntheseType = z.infer; diff --git a/backend/src/common/models/modified-since.enum.ts b/backend/src/common/models/modified-since.enum.ts index 087b7c87fe..16d41729cb 100644 --- a/backend/src/common/models/modified-since.enum.ts +++ b/backend/src/common/models/modified-since.enum.ts @@ -16,7 +16,7 @@ export const modifiedSinceSchema = z.enum([ ]); export const getModifiedSinceDate = ( - modifiedSince: ModifiedSinceEnum, + modifiedSince: ModifiedSinceEnum ): Date => { const now = DateTime.now(); switch (modifiedSince) { diff --git a/backend/src/common/models/version.models.ts b/backend/src/common/models/version.models.ts index f6ff4aa5e6..46ecb0a95c 100644 --- a/backend/src/common/models/version.models.ts +++ b/backend/src/common/models/version.models.ts @@ -1,5 +1,6 @@ import { extendApi, extendZodWithOpenApi } from '@anatine/zod-openapi'; import { z } from 'zod'; + extendZodWithOpenApi(z); export enum AppEnvironment { @@ -25,6 +26,6 @@ export const versionResponseSchema = extendApi( deploy_time: z.string().openapi({ description: 'Date de déploiement au format ISO 8601', }), - }), + }) ); export type VersionResponseType = z.infer; diff --git a/backend/src/common/services/gcloud.helper.ts b/backend/src/common/services/gcloud.helper.ts index b7585d25de..8af3d43d0c 100644 --- a/backend/src/common/services/gcloud.helper.ts +++ b/backend/src/common/services/gcloud.helper.ts @@ -10,11 +10,11 @@ export const initApplicationCredentials = () => { ) { const serviceAccountFile = `${__dirname}/keyfile.json`; logger.log( - `Writing Google Cloud credentials to file: ${serviceAccountFile}`, + `Writing Google Cloud credentials to file: ${serviceAccountFile}` ); fs.writeFileSync( serviceAccountFile, - process.env.GCLOUD_SERVICE_ACCOUNT_KEY, + process.env.GCLOUD_SERVICE_ACCOUNT_KEY ); process.env.GOOGLE_APPLICATION_CREDENTIALS = serviceAccountFile; } diff --git a/backend/src/config/configuration.model.ts b/backend/src/config/configuration.model.ts index 771d817c8f..09489cec73 100644 --- a/backend/src/config/configuration.model.ts +++ b/backend/src/config/configuration.model.ts @@ -1,5 +1,6 @@ import { extendZodWithOpenApi } from '@anatine/zod-openapi'; import { z } from 'zod'; + extendZodWithOpenApi(z); export const backendConfigurationSchema = z.object({ @@ -36,12 +37,10 @@ export const backendConfigurationSchema = z.object({ 'Identifiant du dossier Google Drive pour le stockage des résultats de calcul de la trajectoire SNBC', }), DIRECTUS_API_KEY: z.string().min(1).openapi({ - description: - "Clé pour la connexion à l'api de Directus" + description: "Clé pour la connexion à l'api de Directus", }), BREVO_API_KEY: z.string().min(1).openapi({ - description: - "Clé pour la connexion à l'api de Brevo" + description: "Clé pour la connexion à l'api de Brevo", }), }); export type BackendConfigurationType = z.infer< diff --git a/backend/src/directus/models/directus.models.ts b/backend/src/directus/models/directus.models.ts index 03769d947f..00cb17c781 100644 --- a/backend/src/directus/models/directus.models.ts +++ b/backend/src/directus/models/directus.models.ts @@ -2,7 +2,6 @@ * Liste les types retournés par l'api de directus */ - export type Link = { label: string; url: string; diff --git a/backend/src/directus/service/directus.service.ts b/backend/src/directus/service/directus.service.ts index 26f16b8cc3..63c7c42605 100644 --- a/backend/src/directus/service/directus.service.ts +++ b/backend/src/directus/service/directus.service.ts @@ -10,9 +10,7 @@ import ConfigurationService from 'backend/src/config/configuration.service'; export default class DirectusService { private readonly logger = new Logger(DirectusService.name); - constructor( - private readonly configurationService: ConfigurationService, - ) {} + constructor(private readonly configurationService: ConfigurationService) {} private readonly directusKey = this.configurationService.get('DIRECTUS_API_KEY'); @@ -32,7 +30,7 @@ export default class DirectusService { { method: 'GET', headers: this.headers, - }, + } ); if (!response.ok) { diff --git a/backend/src/documents/models/document-lien.dto.ts b/backend/src/documents/models/document-lien.dto.ts index 6efcfcc37d..5551c70365 100644 --- a/backend/src/documents/models/document-lien.dto.ts +++ b/backend/src/documents/models/document-lien.dto.ts @@ -14,5 +14,5 @@ export const lienSchema = extendApi( }) .openapi({ title: 'Un lien URL.', - }), -); \ No newline at end of file + }) +); diff --git a/backend/src/documents/models/document.basetable.ts b/backend/src/documents/models/document.basetable.ts index a70c71a227..040ded7b77 100644 --- a/backend/src/documents/models/document.basetable.ts +++ b/backend/src/documents/models/document.basetable.ts @@ -23,5 +23,3 @@ export const DocumentBase = { modifiedBy: uuid('modified_by'), // TODO references auth.uid, lien: jsonb('lien'), }; - - diff --git a/backend/src/documents/models/preuve-reglementaire-definition.table.ts b/backend/src/documents/models/preuve-reglementaire-definition.table.ts index ba5a56bfbb..ce5b7fee32 100644 --- a/backend/src/documents/models/preuve-reglementaire-definition.table.ts +++ b/backend/src/documents/models/preuve-reglementaire-definition.table.ts @@ -6,5 +6,5 @@ export const preuveReglementaireDefinitionTable = pgTable( id: varchar('id').primaryKey(), nom: text('nom').notNull(), description: text('description').notNull(), - }, + } ); diff --git a/backend/src/documents/services/document.service.ts b/backend/src/documents/services/document.service.ts index 7f44ad4f92..9eab9bfbf8 100644 --- a/backend/src/documents/services/document.service.ts +++ b/backend/src/documents/services/document.service.ts @@ -19,10 +19,10 @@ export default class DocumentService { async createLienAnnexe( ficheId: number, lien: lienType, - collectiviteId: number, + collectiviteId: number ): Promise { this.logger.log( - `Création de l'annexe ${lien.label} pour la collectivité ${collectiviteId}`, + `Création de l'annexe ${lien.label} pour la collectivité ${collectiviteId}` ); const annexeCree = await this.databaseService.db .insert(annexeTable) diff --git a/backend/src/fiches/controllers/fiches-action.controller.ts b/backend/src/fiches/controllers/fiches-action.controller.ts index 351346fdf7..b0482b4620 100644 --- a/backend/src/fiches/controllers/fiches-action.controller.ts +++ b/backend/src/fiches/controllers/fiches-action.controller.ts @@ -13,6 +13,7 @@ import type { SupabaseJwtPayload } from '../../auth/models/supabase-jwt.models'; export class GetFichesActionSyntheseResponseClass extends createZodDto( getFichesActionSyntheseSchema ) {} + export class GetFichesActionFilterRequestClass extends createZodDto( getFichesActionFilterRequestSchema ) {} diff --git a/backend/src/fiches/models/action-impact-fiche-action.table.ts b/backend/src/fiches/models/action-impact-fiche-action.table.ts index e46672a841..667d297653 100644 --- a/backend/src/fiches/models/action-impact-fiche-action.table.ts +++ b/backend/src/fiches/models/action-impact-fiche-action.table.ts @@ -7,12 +7,12 @@ export const actionImpactFicheActionTable = pgTable( { ficheId: integer('fiche_id').references(() => ficheActionTable.id), actionImpactId: integer('action_impact_id').references( - () => actionImpactTable.id, + () => actionImpactTable.id ), }, (table) => { return { pk: primaryKey({ columns: [table.ficheId, table.actionImpactId] }), }; - }, + } ); diff --git a/backend/src/fiches/models/fiche-action-action.table.ts b/backend/src/fiches/models/fiche-action-action.table.ts index b71f94554c..8654b971c1 100644 --- a/backend/src/fiches/models/fiche-action-action.table.ts +++ b/backend/src/fiches/models/fiche-action-action.table.ts @@ -1,9 +1,4 @@ -import { - integer, - pgTable, - primaryKey, - varchar, -} from 'drizzle-orm/pg-core'; +import { integer, pgTable, primaryKey, varchar } from 'drizzle-orm/pg-core'; import { actionRelationTable } from '../../referentiel/models/action-relation.table'; import { ficheActionTable } from './fiche-action.table'; @@ -17,5 +12,5 @@ export const ficheActionActionTable = pgTable( return { pk: primaryKey({ columns: [table.ficheId, table.actionId] }), }; - }, + } ); diff --git a/backend/src/fiches/models/fiche-action-axe.table.ts b/backend/src/fiches/models/fiche-action-axe.table.ts index b924e38011..bbb9dd425a 100644 --- a/backend/src/fiches/models/fiche-action-axe.table.ts +++ b/backend/src/fiches/models/fiche-action-axe.table.ts @@ -12,5 +12,5 @@ export const ficheActionAxeTable = pgTable( return { pk: primaryKey({ columns: [table.ficheId, table.axeId] }), }; - }, + } ); diff --git a/backend/src/fiches/models/fiche-action-effet-attendu.table.ts b/backend/src/fiches/models/fiche-action-effet-attendu.table.ts index 998118357f..f39a33cd01 100644 --- a/backend/src/fiches/models/fiche-action-effet-attendu.table.ts +++ b/backend/src/fiches/models/fiche-action-effet-attendu.table.ts @@ -7,12 +7,12 @@ export const ficheActionEffetAttenduTable = pgTable( { ficheId: integer('fiche_id').references(() => ficheActionTable.id), effetAttenduId: integer('effet_attendu_id').references( - () => effetAttenduTable.id, + () => effetAttenduTable.id ), }, (table) => { return { pk: primaryKey({ columns: [table.ficheId, table.effetAttenduId] }), }; - }, + } ); diff --git a/backend/src/fiches/models/fiche-action-financeur-tag.table.ts b/backend/src/fiches/models/fiche-action-financeur-tag.table.ts index 0aedb5eec4..97280715ae 100644 --- a/backend/src/fiches/models/fiche-action-financeur-tag.table.ts +++ b/backend/src/fiches/models/fiche-action-financeur-tag.table.ts @@ -10,8 +10,8 @@ export const ficheActionFinanceurTagTable = pgTable( .notNull() .references(() => ficheActionTable.id), financeurTagId: integer('financeur_tag_id').references( - () => financeurTagTable.id, + () => financeurTagTable.id ), montantTtc: integer('montant_ttc'), - }, + } ); diff --git a/backend/src/fiches/models/fiche-action-indicateur.table.ts b/backend/src/fiches/models/fiche-action-indicateur.table.ts index 034f5b4db4..78534ae02b 100644 --- a/backend/src/fiches/models/fiche-action-indicateur.table.ts +++ b/backend/src/fiches/models/fiche-action-indicateur.table.ts @@ -7,12 +7,12 @@ export const ficheActionIndicateurTable = pgTable( { ficheId: integer('fiche_id').references(() => ficheActionTable.id), indicateurId: integer('indicateur_id').references( - () => indicateurDefinitionTable.id, + () => indicateurDefinitionTable.id ), }, (table) => { return { pk: primaryKey({ columns: [table.ficheId, table.indicateurId] }), }; - }, + } ); diff --git a/backend/src/fiches/models/fiche-action-lien.table.ts b/backend/src/fiches/models/fiche-action-lien.table.ts index 5dcea8328f..56c07b7de0 100644 --- a/backend/src/fiches/models/fiche-action-lien.table.ts +++ b/backend/src/fiches/models/fiche-action-lien.table.ts @@ -11,5 +11,5 @@ export const ficheActionLienTable = pgTable( return { pk: primaryKey({ columns: [table.ficheUne, table.ficheDeux] }), }; - }, + } ); diff --git a/backend/src/fiches/models/fiche-action-partenaire-tag.table.ts b/backend/src/fiches/models/fiche-action-partenaire-tag.table.ts index a41180c0eb..05d88e421b 100644 --- a/backend/src/fiches/models/fiche-action-partenaire-tag.table.ts +++ b/backend/src/fiches/models/fiche-action-partenaire-tag.table.ts @@ -7,12 +7,12 @@ export const ficheActionPartenaireTagTable = pgTable( { ficheId: integer('fiche_id').references(() => ficheActionTable.id), partenaireTagId: integer('partenaire_tag_id').references( - () => partenaireTagTable.id, + () => partenaireTagTable.id ), }, (table) => { return { pk: primaryKey({ columns: [table.ficheId, table.partenaireTagId] }), }; - }, + } ); diff --git a/backend/src/fiches/models/fiche-action-pilote.table.ts b/backend/src/fiches/models/fiche-action-pilote.table.ts index 834ab11256..225bf789c4 100644 --- a/backend/src/fiches/models/fiche-action-pilote.table.ts +++ b/backend/src/fiches/models/fiche-action-pilote.table.ts @@ -13,12 +13,12 @@ export const ficheActionPiloteTable = pgTable( return { oneUserPerFiche: uniqueIndex('one_user_per_fiche ').on( table.ficheId, - table.userId, + table.userId ), oneTagPerFiche: uniqueIndex('one_tag_per_fiche ').on( table.ficheId, - table.tagId, + table.tagId ), }; - }, + } ); diff --git a/backend/src/fiches/models/fiche-action-referent.table.ts b/backend/src/fiches/models/fiche-action-referent.table.ts index 5bab23559b..96ef37f5ba 100644 --- a/backend/src/fiches/models/fiche-action-referent.table.ts +++ b/backend/src/fiches/models/fiche-action-referent.table.ts @@ -12,8 +12,8 @@ export const ficheActionReferentTable = pgTable( (table) => { return { ficheActionReferentFicheIdUserIdTagIdKey: uniqueIndex( - 'fiche_action_referent_fiche_id_user_id_tag_id_key ', + 'fiche_action_referent_fiche_id_user_id_tag_id_key ' ).on(table.ficheId, table.userId, table.tagId), }; - }, + } ); diff --git a/backend/src/fiches/models/fiche-action-service-tag.table.ts b/backend/src/fiches/models/fiche-action-service-tag.table.ts index b1053354b6..2721efaa61 100644 --- a/backend/src/fiches/models/fiche-action-service-tag.table.ts +++ b/backend/src/fiches/models/fiche-action-service-tag.table.ts @@ -7,12 +7,12 @@ export const ficheActionServiceTagTable = pgTable( { ficheId: integer('fiche_id').references(() => ficheActionTable.id), serviceTagId: integer('service_tag_id').references( - () => serviceTagTable.id, + () => serviceTagTable.id ), }, (table) => { return { pk: primaryKey({ columns: [table.ficheId, table.serviceTagId] }), }; - }, + } ); diff --git a/backend/src/fiches/models/fiche-action-service.table.ts b/backend/src/fiches/models/fiche-action-service.table.ts index b1ed7ed7c1..049c0d8132 100644 --- a/backend/src/fiches/models/fiche-action-service.table.ts +++ b/backend/src/fiches/models/fiche-action-service.table.ts @@ -7,12 +7,12 @@ export const ficheActionServiceTagTable = pgTable( { fiche_id: integer('fiche_id').references(() => ficheActionTable.id), service_tag_id: integer('service_tag_id').references( - () => serviceTagTable.id, + () => serviceTagTable.id ), }, (table) => { return { pk: primaryKey({ columns: [table.fiche_id, table.service_tag_id] }), }; - }, + } ); diff --git a/backend/src/fiches/models/fiche-action-sous-thematique.table.ts b/backend/src/fiches/models/fiche-action-sous-thematique.table.ts index 886c0e97c0..5cbbde2198 100644 --- a/backend/src/fiches/models/fiche-action-sous-thematique.table.ts +++ b/backend/src/fiches/models/fiche-action-sous-thematique.table.ts @@ -7,12 +7,12 @@ export const ficheActionSousThematiqueTable = pgTable( { ficheId: integer('fiche_id').references(() => ficheActionTable.id), thematiqueId: integer('thematique_id').references( - () => sousThematiqueTable.id, + () => sousThematiqueTable.id ), }, (table) => { return { pk: primaryKey({ columns: [table.ficheId, table.thematiqueId] }), }; - }, + } ); diff --git a/backend/src/fiches/models/fiche-action-structure-tag.table.ts b/backend/src/fiches/models/fiche-action-structure-tag.table.ts index 19bdd044b0..a3433af5b8 100644 --- a/backend/src/fiches/models/fiche-action-structure-tag.table.ts +++ b/backend/src/fiches/models/fiche-action-structure-tag.table.ts @@ -7,12 +7,12 @@ export const ficheActionStructureTagTable = pgTable( { ficheId: integer('fiche_id').references(() => ficheActionTable.id), structureTagId: integer('structure_tag_id').references( - () => structureTagTable.id, + () => structureTagTable.id ), }, (table) => { return { pk: primaryKey({ columns: [table.ficheId, table.structureTagId] }), }; - }, + } ); diff --git a/backend/src/fiches/models/fiche-action-thematique.table.ts b/backend/src/fiches/models/fiche-action-thematique.table.ts index c15676e982..f6b1ab2453 100644 --- a/backend/src/fiches/models/fiche-action-thematique.table.ts +++ b/backend/src/fiches/models/fiche-action-thematique.table.ts @@ -12,5 +12,5 @@ export const ficheActionThematiqueTable = pgTable( return { pk: primaryKey({ columns: [table.ficheId, table.thematiqueId] }), }; - }, + } ); diff --git a/backend/src/fiches/models/get-fiches-action-synthese.response.ts b/backend/src/fiches/models/get-fiches-action-synthese.response.ts index 214cb8c479..4e30188d60 100644 --- a/backend/src/fiches/models/get-fiches-action-synthese.response.ts +++ b/backend/src/fiches/models/get-fiches-action-synthese.response.ts @@ -1,12 +1,13 @@ import { extendApi, extendZodWithOpenApi } from '@anatine/zod-openapi'; import { z } from 'zod'; import { countSyntheseSchema } from '../../common/models/count-synthese.dto'; + extendZodWithOpenApi(z); export const getFichesActionSyntheseSchema = extendApi( z.object({ par_statut: countSyntheseSchema, - }), + }) ); export type GetFichesActionSyntheseResponseType = z.infer< diff --git a/backend/src/fiches/models/get-fiches-actions-filter.request.ts b/backend/src/fiches/models/get-fiches-actions-filter.request.ts index 8f24e0dfe0..31904bd5c3 100644 --- a/backend/src/fiches/models/get-fiches-actions-filter.request.ts +++ b/backend/src/fiches/models/get-fiches-actions-filter.request.ts @@ -70,7 +70,7 @@ export const getFichesActionFilterRequestSchema = extendApi( }) .openapi({ title: 'Filtre de récupération des fiches action', - }), + }) ); export type GetFichesActionFilterRequestType = z.infer< typeof getFichesActionFilterRequestSchema diff --git a/backend/src/fiches/models/plan-action-type-categorie.table.ts b/backend/src/fiches/models/plan-action-type-categorie.table.ts index c29ee7c46c..0f584324b8 100644 --- a/backend/src/fiches/models/plan-action-type-categorie.table.ts +++ b/backend/src/fiches/models/plan-action-type-categorie.table.ts @@ -4,5 +4,5 @@ export const planActionTypeCategorieTable = pgTable( 'plan_action_type_categorie', { categorie: text('categorie').primaryKey(), - }, + } ); diff --git a/backend/src/fiches/models/plan-action-type-category.table.ts b/backend/src/fiches/models/plan-action-type-category.table.ts index c29ee7c46c..0f584324b8 100644 --- a/backend/src/fiches/models/plan-action-type-category.table.ts +++ b/backend/src/fiches/models/plan-action-type-category.table.ts @@ -4,5 +4,5 @@ export const planActionTypeCategorieTable = pgTable( 'plan_action_type_categorie', { categorie: text('categorie').primaryKey(), - }, + } ); diff --git a/backend/src/fiches/models/plan-action-type.table.ts b/backend/src/fiches/models/plan-action-type.table.ts index 530457b810..36089114b6 100644 --- a/backend/src/fiches/models/plan-action-type.table.ts +++ b/backend/src/fiches/models/plan-action-type.table.ts @@ -14,8 +14,8 @@ export const planActionTypeTable = pgTable( (table) => { return { planActionTypeCategorieTypeKey: uniqueIndex( - 'plan_action_type_categorie_type_key', + 'plan_action_type_categorie_type_key' ).on(table.categorie, table.type), }; - }, + } ); diff --git a/backend/src/fiches/services/axe.service.ts b/backend/src/fiches/services/axe.service.ts index 25930b8e35..3d2ee4c551 100644 --- a/backend/src/fiches/services/axe.service.ts +++ b/backend/src/fiches/services/axe.service.ts @@ -17,7 +17,7 @@ export default class AxeService { */ async createAxe(axe: CreateAxeType): Promise { this.logger.log( - `Création de l'axe ${axe.nom} pour la collectivité ${axe.collectiviteId}`, + `Création de l'axe ${axe.nom} pour la collectivité ${axe.collectiviteId}` ); const axeCree = await this.databaseService.db .insert(axeTable) @@ -43,11 +43,11 @@ export default class AxeService { or( and( isNull(axeTable.parent), - isNull(axe.parent ? axe.parent : null), + isNull(axe.parent ? axe.parent : null) ), - eq(axeTable.parent, axe.parent), - ), - ), + eq(axeTable.parent, axe.parent) + ) + ) ); const axeExistant = axeExistants?.length > 0 ? axeExistants[0] : null; if (!axeExistant) { diff --git a/backend/src/fiches/services/fiche.service.ts b/backend/src/fiches/services/fiche.service.ts index 9c4dd31030..0f3d5db5d6 100644 --- a/backend/src/fiches/services/fiche.service.ts +++ b/backend/src/fiches/services/fiche.service.ts @@ -19,7 +19,7 @@ export default class FicheService { constructor( private readonly databaseService: DatabaseService, - private readonly tagService: TagService, + private readonly tagService: TagService ) {} /** @@ -29,7 +29,7 @@ export default class FicheService { */ async createFiche(fiche: CreateFicheActionType): Promise { this.logger.log( - `Création de la fiche ${fiche.titre} pour la collectivité ${fiche.collectiviteId}`, + `Création de la fiche ${fiche.titre} pour la collectivité ${fiche.collectiviteId}` ); const ficheCree = await this.databaseService.db .insert(ficheActionTable) @@ -57,7 +57,7 @@ export default class FicheService { */ async addSousThematique( ficheId: number, - thematiqueId: number, + thematiqueId: number ): Promise { await this.databaseService.db .insert(ficheActionSousThematiqueTable) @@ -86,7 +86,7 @@ export default class FicheService { */ async addEffetAttendu( ficheId: number, - effetAttenduId: number, + effetAttenduId: number ): Promise { await this.databaseService.db.insert(ficheActionEffetAttenduTable).values({ ficheId: ficheId, @@ -115,7 +115,7 @@ export default class FicheService { async addPartenaireByNom( ficheId: number, nomTag: string, - collectiviteId: number, + collectiviteId: number ): Promise { const tagId = await this.tagService.getPartenaireId(nomTag, collectiviteId); await this.addPartenaireById(ficheId, tagId); diff --git a/backend/src/fiches/services/fiches-action-synthese.service.ts b/backend/src/fiches/services/fiches-action-synthese.service.ts index de3c3be705..be7f0b5bfb 100644 --- a/backend/src/fiches/services/fiches-action-synthese.service.ts +++ b/backend/src/fiches/services/fiches-action-synthese.service.ts @@ -42,13 +42,13 @@ export default class FichesActionSyntheseService { constructor( private readonly databaseService: DatabaseService, - private readonly authService: AuthService, + private readonly authService: AuthService ) {} async getFichesActionSynthese( collectiviteId: number, filter: GetFichesActionFilterRequestType, - tokenInfo: SupabaseJwtPayload, + tokenInfo: SupabaseJwtPayload ): Promise { this.logger.log( `Récupération de la synthese des fiches action pour la collectivité ${collectiviteId}: filtre ${JSON.stringify( @@ -77,7 +77,7 @@ export default class FichesActionSyntheseService { fiche_id: ficheActionPartenaireTagTable.ficheId, partenaire_tag_ids: sql`array_agg(${ficheActionPartenaireTagTable.partenaireTagId})`.as( - this.FICHE_ACTION_PARTENAIRE_TAGS_QUERY_FIELD, + this.FICHE_ACTION_PARTENAIRE_TAGS_QUERY_FIELD ), }) .from(ficheActionPartenaireTagTable) @@ -104,7 +104,7 @@ export default class FichesActionSyntheseService { fiche_id: ficheActionServiceTagTable.fiche_id, service_tag_ids: sql`array_agg(${ficheActionServiceTagTable.service_tag_id})`.as( - 'service_tag_ids', + 'service_tag_ids' ), }) .from(ficheActionServiceTagTable) @@ -118,11 +118,11 @@ export default class FichesActionSyntheseService { fiche_id: ficheActionPiloteTable.ficheId, pilote_user_ids: sql`array_remove(array_agg(${ficheActionPiloteTable.userId}), NULL)`.as( - 'pilote_user_ids', + 'pilote_user_ids' ), pilote_tag_ids: sql`array_remove(array_agg(${ficheActionPiloteTable.tagId}), NULL)`.as( - 'pilote_tag_ids', + 'pilote_tag_ids' ), }) .from(ficheActionPiloteTable) @@ -133,7 +133,7 @@ export default class FichesActionSyntheseService { async getFichesAction( collectiviteId: number, filter: GetFichesActionFilterRequestType, - tokenInfo: SupabaseJwtPayload, + tokenInfo: SupabaseJwtPayload ): Promise { this.logger.log( `Récupération des fiches action pour la collectivité ${collectiviteId}: filtre ${JSON.stringify( @@ -161,19 +161,19 @@ export default class FichesActionSyntheseService { .from(ficheActionTable) .leftJoin( ficheActionPartenaireTags, - eq(ficheActionPartenaireTags.fiche_id, ficheActionTable.id), + eq(ficheActionPartenaireTags.fiche_id, ficheActionTable.id) ) .leftJoin( ficheActionPilotes, - eq(ficheActionPilotes.fiche_id, ficheActionTable.id), + eq(ficheActionPilotes.fiche_id, ficheActionTable.id) ) .leftJoin( ficheActionServiceTags, - eq(ficheActionServiceTags.fiche_id, ficheActionTable.id), + eq(ficheActionServiceTags.fiche_id, ficheActionTable.id) ) .leftJoin( ficheActionAxes, - eq(ficheActionAxes.fiche_id, ficheActionTable.id), + eq(ficheActionAxes.fiche_id, ficheActionTable.id) ) .where(and(...conditions)); @@ -182,7 +182,7 @@ export default class FichesActionSyntheseService { getConditions( collectiviteId: number, - filter: GetFichesActionFilterRequestType, + filter: GetFichesActionFilterRequestType ): (SQLWrapper | SQL)[] { const conditions: (SQLWrapper | SQL)[] = [ eq(ficheActionTable.collectiviteId, collectiviteId), @@ -193,7 +193,7 @@ export default class FichesActionSyntheseService { if (filter.modified_since) { const modifiedSinceDate = getModifiedSinceDate(filter.modified_since); conditions.push( - gte(ficheActionTable.modifiedAt, modifiedSinceDate.toISOString()), + gte(ficheActionTable.modifiedAt, modifiedSinceDate.toISOString()) ); } if (filter.modified_after) { @@ -203,14 +203,14 @@ export default class FichesActionSyntheseService { // Vraiment étrange, probable bug de drizzle, on le peut pas lui donner le tableau directement const sqlNumberArray = `{${filter.partenaire_tag_ids.join(',')}}`; conditions.push( - arrayOverlaps(sql`partenaire_tag_ids`, sql`${sqlNumberArray}`), + arrayOverlaps(sql`partenaire_tag_ids`, sql`${sqlNumberArray}`) ); } if (filter.service_tag_ids?.length) { // Vraiment étrange, probable bug de drizzle, on le peut pas lui donner le tableau directement const sqlNumberArray = `{${filter.service_tag_ids.join(',')}}`; conditions.push( - arrayOverlaps(sql`service_tag_ids`, sql`${sqlNumberArray}`), + arrayOverlaps(sql`service_tag_ids`, sql`${sqlNumberArray}`) ); } if (filter.plan_ids?.length) { @@ -223,13 +223,13 @@ export default class FichesActionSyntheseService { if (filter.pilote_user_ids?.length) { const sqlNumberArray = `{${filter.pilote_user_ids.join(',')}}`; piloteConditions.push( - arrayOverlaps(sql`pilote_user_ids`, sql`${sqlNumberArray}`), + arrayOverlaps(sql`pilote_user_ids`, sql`${sqlNumberArray}`) ); } if (filter.pilote_tag_ids?.length) { const sqlNumberArray = `{${filter.pilote_tag_ids.join(',')}}`; piloteConditions.push( - arrayOverlaps(sql`pilote_tag_ids`, sql`${sqlNumberArray}`), + arrayOverlaps(sql`pilote_tag_ids`, sql`${sqlNumberArray}`) ); } if (piloteConditions.length) { @@ -266,19 +266,19 @@ export default class FichesActionSyntheseService { .from(ficheActionTable) .leftJoin( ficheActionPartenaireTags, - eq(ficheActionPartenaireTags.fiche_id, ficheActionTable.id), + eq(ficheActionPartenaireTags.fiche_id, ficheActionTable.id) ) .leftJoin( ficheActionPilotes, - eq(ficheActionPilotes.fiche_id, ficheActionTable.id), + eq(ficheActionPilotes.fiche_id, ficheActionTable.id) ) .leftJoin( ficheActionServiceTags, - eq(ficheActionServiceTags.fiche_id, ficheActionTable.id), + eq(ficheActionServiceTags.fiche_id, ficheActionTable.id) ) .leftJoin( ficheActionAxes, - eq(ficheActionAxes.fiche_id, ficheActionTable.id), + eq(ficheActionAxes.fiche_id, ficheActionTable.id) ) .where(and(...conditions)) .groupBy(propriete); diff --git a/backend/src/indicateurs/controllers/indicateurs.controller.ts b/backend/src/indicateurs/controllers/indicateurs.controller.ts index c64b3ce847..02071f8f8b 100644 --- a/backend/src/indicateurs/controllers/indicateurs.controller.ts +++ b/backend/src/indicateurs/controllers/indicateurs.controller.ts @@ -17,11 +17,11 @@ import type { SupabaseJwtPayload } from '../../auth/models/supabase-jwt.models'; * 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 */ class GetIndicateursValeursRequestClass extends createZodDto( - getIndicateursValeursRequestSchema, + getIndicateursValeursRequestSchema ) {} class GetIndicateursValeursResponseClass extends createZodDto( - getIndicateursValeursResponseSchema, + getIndicateursValeursResponseSchema ) {} @ApiTags('Indicateurs') @@ -35,11 +35,11 @@ export class IndicateursController { @ApiResponse({ type: GetIndicateursValeursResponseClass }) async getIndicateurValeurs( @Query() request: GetIndicateursValeursRequestClass, - @TokenInfo() tokenInfo: SupabaseJwtPayload, + @TokenInfo() tokenInfo: SupabaseJwtPayload ): Promise { return this.indicateurService.getIndicateurValeursGroupees( request, - tokenInfo, + tokenInfo ); } @@ -49,12 +49,12 @@ export class IndicateursController { }) async upsertIndicateurValeurs( @Body() request: UpsertIndicateursValeursRequest, - @TokenInfo() tokenInfo: SupabaseJwtPayload, + @TokenInfo() tokenInfo: SupabaseJwtPayload ): Promise { const upsertedValeurs = await this.indicateurService.upsertIndicateurValeurs( request.valeurs, - tokenInfo, + tokenInfo ); return { valeurs: upsertedValeurs }; } diff --git a/backend/src/indicateurs/controllers/trajectoires.controller.ts b/backend/src/indicateurs/controllers/trajectoires.controller.ts index 09339de31c..fdbc2e589a 100644 --- a/backend/src/indicateurs/controllers/trajectoires.controller.ts +++ b/backend/src/indicateurs/controllers/trajectoires.controller.ts @@ -29,21 +29,23 @@ import type { SupabaseJwtPayload } from '../../auth/models/supabase-jwt.models'; * 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, + calculTrajectoireResponseSchema ) {} + export class CalculTrajectoireRequestClass extends createZodDto( - calculTrajectoireRequestSchema, + calculTrajectoireRequestSchema ) {} export class ModeleTrajectoireTelechargementRequestClass extends createZodDto( - modeleTrajectoireTelechargementRequestSchema, + modeleTrajectoireTelechargementRequestSchema ) {} export class VerificationTrajectoireRequestClass extends createZodDto( - verificationTrajectoireRequestSchema, + verificationTrajectoireRequestSchema ) {} + export class VerificationDonneesSNBCResponseClass extends createZodDto( - verificationDonneesSNBCResponseSchema, + verificationDonneesSNBCResponseSchema ) {} @ApiTags('Trajectoires') @@ -54,23 +56,23 @@ export class TrajectoiresController { constructor( private readonly trajectoiresDataService: TrajectoiresDataService, private readonly trajectoiresSpreadsheetService: TrajectoiresSpreadsheetService, - private readonly trajectoiresXlsxService: TrajectoiresXlsxService, + private readonly trajectoiresXlsxService: TrajectoiresXlsxService ) {} @Get('') @ApiResponse({ type: CalculTrajectoireResponseClass }) async calculeTrajectoireSnbc( @Query() request: CalculTrajectoireRequestClass, - @TokenInfo() tokenInfo: SupabaseJwtPayload, + @TokenInfo() tokenInfo: SupabaseJwtPayload ): Promise { this.logger.log( - `Calcul de la trajectoire SNBC pour la collectivité ${request.collectivite_id}`, + `Calcul de la trajectoire SNBC pour la collectivité ${request.collectivite_id}` ); // eslint-disable-next-line @typescript-eslint/no-unused-vars const { spreadsheet_id, ...response } = await this.trajectoiresSpreadsheetService.calculeTrajectoireSnbc( request, - tokenInfo, + tokenInfo ); return response; } @@ -78,15 +80,15 @@ export class TrajectoiresController { @Delete('') async deleteTrajectoireSnbc( @Query() request: CollectiviteRequestClass, - @TokenInfo() tokenInfo: SupabaseJwtPayload, + @TokenInfo() tokenInfo: SupabaseJwtPayload ): Promise { this.logger.log( - `Suppression de la trajectoire SNBC pour la collectivité ${request.collectivite_id}`, + `Suppression de la trajectoire SNBC pour la collectivité ${request.collectivite_id}` ); await this.trajectoiresDataService.deleteTrajectoireSnbc( request.collectivite_id, undefined, - tokenInfo, + tokenInfo ); } @@ -99,13 +101,13 @@ export class TrajectoiresController { downloadModeleSnbc( @Query() request: ModeleTrajectoireTelechargementRequestClass, @Res() res: Response, - @Next() next: NextFunction, + @Next() next: NextFunction ) { this.logger.log(`Téléchargement du modele de trajectoire SNBC`); this.trajectoiresXlsxService.downloadModeleTrajectoireSnbc( request, res, - next, + next ); } @@ -118,16 +120,16 @@ export class TrajectoiresController { @Query() request: CollectiviteRequestClass, @TokenInfo() tokenInfo: SupabaseJwtPayload, @Res() res: Response, - @Next() next: NextFunction, + @Next() next: NextFunction ) { this.logger.log( - `Téléchargement de la trajectoire SNBC pour la collectivité ${request.collectivite_id}`, + `Téléchargement de la trajectoire SNBC pour la collectivité ${request.collectivite_id}` ); this.trajectoiresXlsxService.downloadTrajectoireSnbc( request, tokenInfo, res, - next, + next ); } @@ -139,16 +141,16 @@ export class TrajectoiresController { }) async verificationDonneesSnbc( @Query() request: VerificationTrajectoireRequestClass, - @TokenInfo() tokenInfo: SupabaseJwtPayload, + @TokenInfo() tokenInfo: SupabaseJwtPayload ): Promise { this.logger.log( - `Vérifie la possibilité de lancer le calcul de la trajectoire SNBC pour la collectivité ${request.collectivite_id}`, + `Vérifie la possibilité de lancer le calcul de la trajectoire SNBC pour la collectivité ${request.collectivite_id}` ); // eslint-disable-next-line @typescript-eslint/no-unused-vars const { valeurs, ...response } = await this.trajectoiresDataService.verificationDonneesSnbc( request, - tokenInfo, + tokenInfo ); if (!request.epci_info) { delete response.epci; diff --git a/backend/src/indicateurs/models/calcultrajectoire.models.ts b/backend/src/indicateurs/models/calcultrajectoire.models.ts index c33306c3b9..353c81bded 100644 --- a/backend/src/indicateurs/models/calcultrajectoire.models.ts +++ b/backend/src/indicateurs/models/calcultrajectoire.models.ts @@ -30,7 +30,7 @@ export const modeleTrajectoireTelechargementRequestSchema = extendApi( description: 'Récupère les données du fichier xlsx depuis le drive plutôt que le cache local', }), - }), + }) ); export type ModeleTrajectoireTelechargementRequestType = z.infer< typeof modeleTrajectoireTelechargementRequestSchema @@ -61,7 +61,7 @@ export const verificationTrajectoireRequestSchema = extendApi( description: "Force l'utilisation des données de la collectivité plutôt que celles du rare", }), - }), + }) ); export type VerificationTrajectoireRequestType = z.infer< typeof verificationTrajectoireRequestSchema @@ -80,7 +80,7 @@ export const donneesARemplirValeurSchema = extendApi( valeur: z.number().nullable(), date_min: z.string().nullable(), date_max: z.string().nullable(), - }), + }) ); export type DonneesARemplirValeurType = z.infer< typeof donneesARemplirValeurSchema @@ -90,7 +90,7 @@ export const donneesARemplirResultSchema = extendApi( z.object({ valeurs: z.array(donneesARemplirValeurSchema), identifiants_referentiel_manquants: z.array(z.string()), - }), + }) ); export type DonneesARemplirResultType = z.infer< typeof donneesARemplirResultSchema @@ -102,7 +102,7 @@ export const donneesCalculTrajectoireARemplirSchema = extendApi( emissions_ges: donneesARemplirResultSchema, consommations_finales: donneesARemplirResultSchema, sequestrations: donneesARemplirResultSchema, - }), + }) ); export type DonneesCalculTrajectoireARemplirType = z.infer< typeof donneesCalculTrajectoireARemplirSchema @@ -132,7 +132,7 @@ export const verificationDonneesSNBCResponseSchema = extendApi( description: "Identifiants du référentiel manquants dans les données d'entrée lorsque le calcul a déjà été fait", }), - }), + }) ); export type VerificationDonneesSNBCResponseType = z.infer< typeof verificationDonneesSNBCResponseSchema @@ -156,7 +156,7 @@ export const calculTrajectoireRequestSchema = extendApi( description: "Force l'utilisation des données de la collectivité plutôt que celles du rare", }), - }), + }) ); export type CalculTrajectoireRequestType = z.infer< typeof calculTrajectoireRequestSchema @@ -171,7 +171,7 @@ export const calculTrajectoireResponseDonneesSchema = extendApi( }) .openapi({ title: 'Données de la trajectoire SNBC', - }), + }) ); export type CalculTrajectoireResponseDonneesType = z.infer< typeof calculTrajectoireResponseDonneesSchema @@ -187,7 +187,7 @@ export const calculTrajectoireResponseSchema = extendApi( }) .openapi({ title: 'Réponse du calcul de la trajectoire SNBC', - }), + }) ); export type CalculTrajectoireResponseType = z.infer< typeof calculTrajectoireResponseSchema diff --git a/backend/src/indicateurs/models/deleteIndicateurs.models.ts b/backend/src/indicateurs/models/deleteIndicateurs.models.ts index fa296e0fc4..3c896107de 100644 --- a/backend/src/indicateurs/models/deleteIndicateurs.models.ts +++ b/backend/src/indicateurs/models/deleteIndicateurs.models.ts @@ -17,7 +17,7 @@ export const deleteIndicateursValeursRequestSchema = extendApi( }) .openapi({ title: 'Filtre de suppression des valeurs des indicateurs', - }), + }) ); export type DeleteIndicateursValeursRequestType = z.infer< typeof deleteIndicateursValeursRequestSchema @@ -30,7 +30,7 @@ export const deleteIndicateursValeursResponseSchema = extendApi( }) .openapi({ title: 'Identifiant des valeurs supprimées', - }), + }) ); export type DeleteIndicateursValeursResponseType = z.infer< diff --git a/backend/src/indicateurs/models/getIndicateurs.models.ts b/backend/src/indicateurs/models/getIndicateurs.models.ts index f1beb9d48c..51f477d558 100644 --- a/backend/src/indicateurs/models/getIndicateurs.models.ts +++ b/backend/src/indicateurs/models/getIndicateurs.models.ts @@ -45,7 +45,7 @@ export const getIndicateursValeursRequestSchema = extendApi( }) .openapi({ title: 'Filtre de récupération des valeurs des indicateurs', - }), + }) ); export type GetIndicateursValeursRequestType = z.infer< typeof getIndicateursValeursRequestSchema @@ -58,7 +58,7 @@ export const getIndicateursValeursResponseSchema = extendApi( }) .openapi({ title: 'Valeurs par indicateur et par source', - }), + }) ); export type GetIndicateursValeursResponseType = z.infer< diff --git a/backend/src/indicateurs/models/indicateur-definition.table.ts b/backend/src/indicateurs/models/indicateur-definition.table.ts index 28c3bb2852..7f23dd124d 100644 --- a/backend/src/indicateurs/models/indicateur-definition.table.ts +++ b/backend/src/indicateurs/models/indicateur-definition.table.ts @@ -1,4 +1,13 @@ -import { boolean, doublePrecision, integer, pgTable, serial, text, timestamp, uuid } from 'drizzle-orm/pg-core'; +import { + boolean, + doublePrecision, + integer, + pgTable, + serial, + text, + timestamp, + uuid, +} from 'drizzle-orm/pg-core'; import { collectiviteTable } from '../../collectivites/models/collectivite.table'; import { InferInsertModel, InferSelectModel, sql } from 'drizzle-orm'; import { createInsertSchema, createSelectSchema } from 'drizzle-zod'; @@ -11,7 +20,7 @@ export const indicateurDefinitionTable = pgTable('indicateur_definition', { () => collectiviteTable.id, { onDelete: 'cascade', - }, + } ), identifiantReferentiel: text('identifiant_referentiel').unique(), titre: text('titre').notNull(), @@ -41,10 +50,10 @@ export type CreateIndicateurDefinitionType = InferInsertModel< typeof indicateurDefinitionTable >; export const indicateurDefinitionSchema = createSelectSchema( - indicateurDefinitionTable, + indicateurDefinitionTable ); export const createIndicateurDefinitionSchema = createInsertSchema( - indicateurDefinitionTable, + indicateurDefinitionTable ); export const minimaleIndicateurDefinitionSchema = indicateurDefinitionSchema.pick({ diff --git a/backend/src/indicateurs/models/indicateur-source-metadonnee.table.ts b/backend/src/indicateurs/models/indicateur-source-metadonnee.table.ts index 92ea6c8300..640f950cf1 100644 --- a/backend/src/indicateurs/models/indicateur-source-metadonnee.table.ts +++ b/backend/src/indicateurs/models/indicateur-source-metadonnee.table.ts @@ -16,7 +16,7 @@ export const indicateurSourceMetadonneeTable = pgTable( producteur: text('producteur'), methodologie: text('methodologie'), limites: text('limites'), - }, + } ); export type IndicateurSourceMetadonneeType = InferSelectModel< typeof indicateurSourceMetadonneeTable @@ -25,8 +25,8 @@ export type CreateIndicateurSourceMetadonneeType = InferInsertModel< typeof indicateurSourceMetadonneeTable >; export const indicateurSourceMetadonneeSchema = createSelectSchema( - indicateurSourceMetadonneeTable, + indicateurSourceMetadonneeTable ); export const createIndicateurSourceMetadonneeSchema = createInsertSchema( - indicateurSourceMetadonneeTable, + indicateurSourceMetadonneeTable ); diff --git a/backend/src/indicateurs/models/indicateur-valeur.table.ts b/backend/src/indicateurs/models/indicateur-valeur.table.ts index b0dd58d81b..a4f0d753d8 100644 --- a/backend/src/indicateurs/models/indicateur-valeur.table.ts +++ b/backend/src/indicateurs/models/indicateur-valeur.table.ts @@ -25,6 +25,7 @@ import { indicateurSourceMetadonneeTable, IndicateurSourceMetadonneeType, } from './indicateur-source-metadonnee.table'; + extendZodWithOpenApi(z); export const indicateurValeurTable = pgTable('indicateur_valeur', { @@ -44,7 +45,7 @@ export const indicateurValeurTable = pgTable('indicateur_valeur', { () => indicateurSourceMetadonneeTable.id, { onDelete: 'cascade', - }, + } ), resultat: doublePrecision('resultat'), resultatCommentaire: text('resultat_commentaire'), @@ -69,7 +70,7 @@ export type CreateIndicateurValeurType = InferInsertModel< >; export const indicateurValeurSchema = createSelectSchema(indicateurValeurTable); export const createIndicateurValeurSchema = createInsertSchema( - indicateurValeurTable, + indicateurValeurTable ); export const indicateurValeurGroupeeSchema = extendApi( @@ -89,7 +90,7 @@ export const indicateurValeurGroupeeSchema = extendApi( objectif: true, objectifCommentaire: true, metadonneeId: true, - }), + }) ); export type IndicateurValeurGroupeeType = z.infer< @@ -97,7 +98,7 @@ export type IndicateurValeurGroupeeType = z.infer< >; export class IndicateurValeurGroupee extends createZodDto( - indicateurValeurGroupeeSchema, + indicateurValeurGroupeeSchema ) {} export const indicateurAvecValeursSchema = extendApi( @@ -108,14 +109,15 @@ export const indicateurAvecValeursSchema = extendApi( }) .openapi({ title: 'Indicateur définition et valeurs ordonnées par date', - }), + }) ); export type IndicateurAvecValeursType = z.infer< typeof indicateurAvecValeursSchema >; + export class IndicateurAvecValeursClass extends createZodDto( - indicateurAvecValeursSchema, + indicateurAvecValeursSchema ) {} export const indicateurValeursGroupeeParSourceSchema = extendApi( @@ -127,10 +129,11 @@ export const indicateurValeursGroupeeParSourceSchema = extendApi( }) .openapi({ title: 'Indicateur valeurs pour une source donnée', - }), + }) ); + export class IndicateurValeursGroupeeParSource extends createZodDto( - indicateurValeursGroupeeParSourceSchema, + indicateurValeursGroupeeParSourceSchema ) {} export const indicateurAvecValeursParSourceSchema = extendApi( @@ -141,10 +144,11 @@ export const indicateurAvecValeursParSourceSchema = extendApi( }) .openapi({ title: 'Filtre de récupération des valeurs des indicateurs', - }), + }) ); + export class IndicateurAvecValeursParSource extends createZodDto( - indicateurAvecValeursParSourceSchema, + indicateurAvecValeursParSourceSchema ) {} export interface IndicateurValeurAvecMetadonnesDefinition { diff --git a/backend/src/indicateurs/models/upsertIndicateurs.models.ts b/backend/src/indicateurs/models/upsertIndicateurs.models.ts index c5dda6171b..5dbcd179f5 100644 --- a/backend/src/indicateurs/models/upsertIndicateurs.models.ts +++ b/backend/src/indicateurs/models/upsertIndicateurs.models.ts @@ -2,6 +2,7 @@ import { createZodDto } from '@anatine/zod-nestjs'; import { extendApi, extendZodWithOpenApi } from '@anatine/zod-openapi'; import { z } from 'zod'; import { createIndicateurValeurSchema } from './indicateur-valeur.table'; + extendZodWithOpenApi(z); export const upsertIndicateursValeursRequestSchema = extendApi( @@ -10,18 +11,19 @@ export const upsertIndicateursValeursRequestSchema = extendApi( valeurs: extendApi( z.array(createIndicateurValeurSchema).min(1).openapi({ description: 'Liste de valeurs', - }), + }) ), }) .openapi({ title: 'Valeurs des indicateurs à insérer ou mettre à jour', - }), + }) ); export type UpsertIndicateursValeursRequestType = z.infer< typeof upsertIndicateursValeursRequestSchema >; + export class UpsertIndicateursValeursRequest extends createZodDto( - upsertIndicateursValeursRequestSchema, + upsertIndicateursValeursRequestSchema ) {} export type UpsertIndicateursValeursResponse = UpsertIndicateursValeursRequest; diff --git a/backend/src/indicateurs/routers/trajectoires.router.ts b/backend/src/indicateurs/routers/trajectoires.router.ts index aaa47c3b64..38e38ebd32 100644 --- a/backend/src/indicateurs/routers/trajectoires.router.ts +++ b/backend/src/indicateurs/routers/trajectoires.router.ts @@ -11,7 +11,7 @@ import TrajectoiresSpreadsheetService from '../services/trajectoires-spreadsheet export class TrajectoiresRouter { constructor( private readonly trpc: TrpcService, - private readonly trajectoiresSpreadsheetService: TrajectoiresSpreadsheetService, + private readonly trajectoiresSpreadsheetService: TrajectoiresSpreadsheetService ) {} router = this.trpc.router({ @@ -20,7 +20,7 @@ export class TrajectoiresRouter { z.object({ collectivite_id: z.number(), conserve_fichier_temporaire: z.boolean().optional(), - }), + }) ) .query(({ input }) => { // TODO: token @@ -31,7 +31,7 @@ export class TrajectoiresRouter { }; return this.trajectoiresSpreadsheetService.calculeTrajectoireSnbc( input, - tokenInfo, + tokenInfo ); }), }); diff --git a/backend/src/indicateurs/services/indicateurSources.service.ts b/backend/src/indicateurs/services/indicateurSources.service.ts index 55602d767a..8012c358be 100644 --- a/backend/src/indicateurs/services/indicateurSources.service.ts +++ b/backend/src/indicateurs/services/indicateurSources.service.ts @@ -18,10 +18,12 @@ export default class IndicateurSourcesService { constructor(private readonly databaseService: DatabaseService) {} async createIndicateurSourceMetadonnee( - indicateurSourceMetadonneeType: CreateIndicateurSourceMetadonneeType, + indicateurSourceMetadonneeType: CreateIndicateurSourceMetadonneeType ) { this.logger.log( - `Création de la metadonnees pour la source d'indicateur ${indicateurSourceMetadonneeType.sourceId} et la date ${indicateurSourceMetadonneeType.dateVersion.toISOString()}`, + `Création de la metadonnees pour la source d'indicateur ${ + indicateurSourceMetadonneeType.sourceId + } et la date ${indicateurSourceMetadonneeType.dateVersion.toISOString()}` ); const request = this.databaseService.db .insert(indicateurSourceMetadonneeTable) @@ -34,10 +36,10 @@ export default class IndicateurSourcesService { async getIndicateurSourceMetadonnee( sourceId: string, - dateVersion: Date, + dateVersion: Date ): Promise { this.logger.log( - `Récupération de la metadonnees pour la source d'indicateur ${sourceId} et la date ${dateVersion.toISOString()}`, + `Récupération de la metadonnees pour la source d'indicateur ${sourceId} et la date ${dateVersion.toISOString()}` ); const indicateurSourceMetadonnees = await this.databaseService.db .select() @@ -45,8 +47,8 @@ export default class IndicateurSourcesService { .where( and( eq(indicateurSourceMetadonneeTable.sourceId, sourceId), - eq(indicateurSourceMetadonneeTable.dateVersion, dateVersion), - ), + eq(indicateurSourceMetadonneeTable.dateVersion, dateVersion) + ) ) .limit(1); return indicateurSourceMetadonnees.length > 0 diff --git a/backend/src/indicateurs/services/indicateurs.service.spec.ts b/backend/src/indicateurs/services/indicateurs.service.spec.ts index 0c0c31ab4a..a3e36cadb2 100644 --- a/backend/src/indicateurs/services/indicateurs.service.spec.ts +++ b/backend/src/indicateurs/services/indicateurs.service.spec.ts @@ -150,7 +150,7 @@ describe('IndicateursService', () => { const indicateurValeursGroupees = indicateurService.groupeIndicateursValeursParIndicateur( indicateurValeurs, - indicateurDefinitions, + indicateurDefinitions ); const expectedIndicateurValeursGroupees: IndicateurAvecValeursType[] = [ { @@ -200,7 +200,7 @@ describe('IndicateursService', () => { ]; expect(indicateurValeursGroupees).toEqual( - expectedIndicateurValeursGroupees, + expectedIndicateurValeursGroupees ); }); }); @@ -365,7 +365,7 @@ describe('IndicateursService', () => { indicateurService.groupeIndicateursValeursParIndicateurEtSource( indicateurValeurs, indicateurDefinitions, - indicateurMetadonnees, + indicateurMetadonnees ); const expectedIndicateurValeursGroupees: IndicateurAvecValeursParSource[] = [ @@ -386,10 +386,10 @@ describe('IndicateursService', () => { sansValeurUtilisateur: false, valeurCalcule: null, modifiedAt: DateTime.fromISO( - '2024-08-12T12:07:14.638Z', + '2024-08-12T12:07:14.638Z' ).toJSDate(), createdAt: DateTime.fromISO( - '2024-08-12T12:07:14.638Z', + '2024-08-12T12:07:14.638Z' ).toJSDate(), modifiedBy: null, createdBy: null, @@ -402,7 +402,7 @@ describe('IndicateursService', () => { id: 1, sourceId: 'rare', dateVersion: DateTime.fromISO( - '2024-07-18T00:00:00.000Z', + '2024-07-18T00:00:00.000Z' ).toJSDate(), nomDonnees: '', diffuseur: 'OREC', @@ -452,10 +452,10 @@ describe('IndicateursService', () => { sansValeurUtilisateur: false, valeurCalcule: null, modifiedAt: DateTime.fromISO( - '2024-08-12T12:07:14.638Z', + '2024-08-12T12:07:14.638Z' ).toJSDate(), createdAt: DateTime.fromISO( - '2024-08-12T12:07:14.638Z', + '2024-08-12T12:07:14.638Z' ).toJSDate(), modifiedBy: null, createdBy: null, @@ -478,7 +478,7 @@ describe('IndicateursService', () => { ]; expect(indicateurValeursGroupees).toEqual( - expectedIndicateurValeursGroupees, + expectedIndicateurValeursGroupees ); }); }); @@ -527,7 +527,7 @@ describe('IndicateursService', () => { id: 1, sourceId: 'rare', dateVersion: DateTime.fromISO( - '2024-07-18T00:00:00.000Z', + '2024-07-18T00:00:00.000Z' ).toJSDate(), nomDonnees: '', diffuseur: 'OREC', @@ -577,7 +577,7 @@ describe('IndicateursService', () => { id: 2, sourceId: 'snbc', dateVersion: DateTime.fromISO( - '2024-07-11T00:00:00.000Z', + '2024-07-11T00:00:00.000Z' ).toJSDate(), nomDonnees: null, diffuseur: null, @@ -589,7 +589,7 @@ describe('IndicateursService', () => { ]; const indicateurValeursDedoublonnees = indicateurService.dedoublonnageIndicateurValeursParSource( - indicateurValeurs, + indicateurValeurs ); // Même date mais deux sources différentes, on ne doit pas dédoublonner @@ -597,7 +597,7 @@ describe('IndicateursService', () => { _.cloneDeep(indicateurValeurs); expect(indicateurValeursDedoublonnees).toEqual( - indicateurValeursDedoublonneesAttendues, + indicateurValeursDedoublonneesAttendues ); }); @@ -644,7 +644,7 @@ describe('IndicateursService', () => { id: 1, sourceId: 'rare', dateVersion: DateTime.fromISO( - '2024-07-18T00:00:00.000Z', + '2024-07-18T00:00:00.000Z' ).toJSDate(), nomDonnees: '', diffuseur: 'OREC', @@ -693,7 +693,7 @@ describe('IndicateursService', () => { id: 1, sourceId: 'rare', dateVersion: DateTime.fromISO( - '2024-07-18T00:00:00.000Z', + '2024-07-18T00:00:00.000Z' ).toJSDate(), nomDonnees: '', diffuseur: 'OREC', @@ -705,7 +705,7 @@ describe('IndicateursService', () => { ]; const indicateurValeursDedoublonnees = indicateurService.dedoublonnageIndicateurValeursParSource( - indicateurValeurs, + indicateurValeurs ); // Même date mais deux indicateurs différents, on ne doit pas dédoublonner @@ -713,7 +713,7 @@ describe('IndicateursService', () => { _.cloneDeep(indicateurValeurs); expect(indicateurValeursDedoublonnees).toEqual( - indicateurValeursDedoublonneesAttendues, + indicateurValeursDedoublonneesAttendues ); }); @@ -760,7 +760,7 @@ describe('IndicateursService', () => { id: 1, sourceId: 'rare', dateVersion: DateTime.fromISO( - '2024-07-18T00:00:00.000Z', + '2024-07-18T00:00:00.000Z' ).toJSDate(), nomDonnees: '', diffuseur: 'OREC', @@ -811,7 +811,7 @@ describe('IndicateursService', () => { ]; const indicateurValeursDedoublonnees = indicateurService.dedoublonnageIndicateurValeursParSource( - indicateurValeurs, + indicateurValeurs ); // Même date mais deux sources différentes, on ne doit pas dédoublonner @@ -819,7 +819,7 @@ describe('IndicateursService', () => { _.cloneDeep(indicateurValeurs); expect(indicateurValeursDedoublonnees).toEqual( - indicateurValeursDedoublonneesAttendues, + indicateurValeursDedoublonneesAttendues ); }); @@ -866,7 +866,7 @@ describe('IndicateursService', () => { id: 1, sourceId: 'rare', dateVersion: DateTime.fromISO( - '2024-07-18T00:00:00.000Z', + '2024-07-18T00:00:00.000Z' ).toJSDate(), nomDonnees: '', diffuseur: 'OREC', @@ -916,7 +916,7 @@ describe('IndicateursService', () => { id: 1, sourceId: 'rare', dateVersion: DateTime.fromISO( - '2024-07-18T00:00:00.000Z', + '2024-07-18T00:00:00.000Z' ).toJSDate(), nomDonnees: '', diffuseur: 'OREC', @@ -928,7 +928,7 @@ describe('IndicateursService', () => { ]; const indicateurValeursDedoublonnees = indicateurService.dedoublonnageIndicateurValeursParSource( - indicateurValeurs, + indicateurValeurs ); // Deux collectivités différentes, on ne doit pas dédoublonner @@ -936,7 +936,7 @@ describe('IndicateursService', () => { _.cloneDeep(indicateurValeurs); expect(indicateurValeursDedoublonnees).toEqual( - indicateurValeursDedoublonneesAttendues, + indicateurValeursDedoublonneesAttendues ); }); @@ -983,7 +983,7 @@ describe('IndicateursService', () => { id: 1, sourceId: 'rare', dateVersion: DateTime.fromISO( - '2024-07-18T00:00:00.000Z', + '2024-07-18T00:00:00.000Z' ).toJSDate(), nomDonnees: '', diffuseur: 'OREC', @@ -1033,7 +1033,7 @@ describe('IndicateursService', () => { id: 1, sourceId: 'rare', dateVersion: DateTime.fromISO( - '2024-07-18T00:00:00.000Z', + '2024-07-18T00:00:00.000Z' ).toJSDate(), nomDonnees: '', diffuseur: 'OREC', @@ -1045,7 +1045,7 @@ describe('IndicateursService', () => { ]; const indicateurValeursDedoublonnees = indicateurService.dedoublonnageIndicateurValeursParSource( - indicateurValeurs, + indicateurValeurs ); // Même source mais deux dates différentes, on ne doit pas dédoublonner @@ -1053,7 +1053,7 @@ describe('IndicateursService', () => { _.cloneDeep(indicateurValeurs); expect(indicateurValeursDedoublonnees).toEqual( - indicateurValeursDedoublonneesAttendues, + indicateurValeursDedoublonneesAttendues ); }); @@ -1163,7 +1163,7 @@ describe('IndicateursService', () => { [_.cloneDeep(indicateurValeur2)]; expect(indicateurValeursDedoublonnees).toEqual( - indicateurValeursDedoublonneesAttendues, + indicateurValeursDedoublonneesAttendues ); // On inverse l'ordre des valeurs @@ -1174,7 +1174,7 @@ describe('IndicateursService', () => { ]); expect(indicateurValeursDedoublonnees2).toEqual( - indicateurValeursDedoublonneesAttendues, + indicateurValeursDedoublonneesAttendues ); }); @@ -1237,7 +1237,7 @@ describe('IndicateursService', () => { [_.cloneDeep(indicateurValeur1)]; expect(indicateurValeursDedoublonnees).toEqual( - indicateurValeursDedoublonneesAttendues, + indicateurValeursDedoublonneesAttendues ); }); }); diff --git a/backend/src/indicateurs/services/indicateurs.service.ts b/backend/src/indicateurs/services/indicateurs.service.ts index 07efd64db6..76345a4864 100644 --- a/backend/src/indicateurs/services/indicateurs.service.ts +++ b/backend/src/indicateurs/services/indicateurs.service.ts @@ -11,13 +11,11 @@ import { or, sql, SQL, - SQLWrapper + SQLWrapper, } from 'drizzle-orm'; import { groupBy, partition } from 'es-toolkit'; import * as _ from 'lodash'; -import { - NiveauAcces, -} from '../../auth/models/private-utilisateur-droit.table'; +import { NiveauAcces } from '../../auth/models/private-utilisateur-droit.table'; import { AuthService } from '../../auth/services/auth.service'; import DatabaseService from '../../common/services/database.service'; import { DeleteIndicateursValeursRequestType } from '../models/deleteIndicateurs.models'; @@ -46,7 +44,10 @@ import { indicateurSourceMetadonneeTable, IndicateurSourceMetadonneeType, } from '../models/indicateur-source-metadonnee.table'; -import { SupabaseJwtPayload, SupabaseRole } from '../../auth/models/supabase-jwt.models'; +import { + SupabaseJwtPayload, + SupabaseRole, +} from '../../auth/models/supabase-jwt.models'; @Injectable() export default class IndicateursService { @@ -61,11 +62,11 @@ export default class IndicateursService { constructor( private readonly databaseService: DatabaseService, - private readonly authService: AuthService, + private readonly authService: AuthService ) {} private getIndicateurValeursSqlConditions( - options: GetIndicateursValeursRequestType, + options: GetIndicateursValeursRequestType ): (SQLWrapper | SQL)[] { const conditions: (SQLWrapper | SQL)[] = [ eq(indicateurValeurTable.collectiviteId, options.collectiviteId), @@ -77,8 +78,8 @@ export default class IndicateursService { conditions.push( inArray( indicateurDefinitionTable.identifiantReferentiel, - options.identifiantsReferentiel, - ), + options.identifiantsReferentiel + ) ); } if (options.dateDebut) { @@ -94,12 +95,12 @@ export default class IndicateursService { const nullSourceId = options.sources.includes(this.NULL_SOURCE_ID); if (nullSourceId) { const autreSourceIds = options.sources.filter( - (s) => s !== this.NULL_SOURCE_ID, + (s) => s !== this.NULL_SOURCE_ID ); if (autreSourceIds.length) { const orCondition = or( isNull(indicateurSourceMetadonneeTable.sourceId), - inArray(indicateurSourceMetadonneeTable.sourceId, autreSourceIds), + inArray(indicateurSourceMetadonneeTable.sourceId, autreSourceIds) ); if (orCondition) { conditions.push(orCondition); @@ -109,7 +110,7 @@ export default class IndicateursService { } } else { conditions.push( - inArray(indicateurSourceMetadonneeTable.sourceId, options.sources), + inArray(indicateurSourceMetadonneeTable.sourceId, options.sources) ); } } @@ -122,21 +123,21 @@ export default class IndicateursService { * @return les définitions des indicateurs */ async getIndicateursDefinitions( - collectiviteId?: number, + collectiviteId?: number ): Promise { const conditions = []; const conditionPredefini = and( isNull(indicateurDefinitionTable.collectiviteId), - isNull(indicateurDefinitionTable.groupementId), + isNull(indicateurDefinitionTable.groupementId) ); if (collectiviteId) { conditions.push( or( conditionPredefini, eq(indicateurDefinitionTable.collectiviteId, collectiviteId), - eq(groupementCollectiviteTable.collectiviteId, collectiviteId), + eq(groupementCollectiviteTable.collectiviteId, collectiviteId) // TODO tester si ça marche comme ça - ), + ) ); } else { conditions.push(conditionPredefini); @@ -147,13 +148,13 @@ export default class IndicateursService { .from(indicateurDefinitionTable) .leftJoin( groupementTable, - eq(indicateurDefinitionTable.groupementId, groupementTable.id), + eq(indicateurDefinitionTable.groupementId, groupementTable.id) ) .leftJoin( groupementCollectiviteTable, - eq(groupementTable.id, groupementCollectiviteTable.groupementId), + eq(groupementTable.id, groupementCollectiviteTable.groupementId) ) - .where((and)(...conditions)); + .where(and(...conditions)); } /** @@ -178,7 +179,9 @@ export default class IndicateursService { */ async getIndicateursValeurs(options: GetIndicateursValeursRequestType) { this.logger.log( - `Récupération des valeurs des indicateurs selon ces options : ${JSON.stringify(options)}`, + `Récupération des valeurs des indicateurs selon ces options : ${JSON.stringify( + options + )}` ); const conditions = this.getIndicateurValeursSqlConditions(options); @@ -188,14 +191,14 @@ export default class IndicateursService { .from(indicateurValeurTable) .leftJoin( indicateurDefinitionTable, - eq(indicateurValeurTable.indicateurId, indicateurDefinitionTable.id), + eq(indicateurValeurTable.indicateurId, indicateurDefinitionTable.id) ) .leftJoin( indicateurSourceMetadonneeTable, eq( indicateurValeurTable.metadonneeId, - indicateurSourceMetadonneeTable.id, - ), + indicateurSourceMetadonneeTable.id + ) ) .where(and(...conditions)); @@ -205,7 +208,7 @@ export default class IndicateursService { result = this.dedoublonnageIndicateurValeursParSource(result); this.logger.log( - `${result.length} valeurs d'indicateurs après dédoublonnage`, + `${result.length} valeurs d'indicateurs après dédoublonnage` ); } @@ -214,7 +217,9 @@ export default class IndicateursService { async deleteIndicateurValeurs(options: DeleteIndicateursValeursRequestType) { this.logger.log( - `Suppression des valeurs des indicateurs selon ces options : ${JSON.stringify(options)}`, + `Suppression des valeurs des indicateurs selon ces options : ${JSON.stringify( + options + )}` ); const conditions: (SQLWrapper | SQL)[] = [ @@ -222,12 +227,12 @@ export default class IndicateursService { ]; if (options.indicateurId) { conditions.push( - eq(indicateurValeurTable.indicateurId, options.indicateurId), + eq(indicateurValeurTable.indicateurId, options.indicateurId) ); } if (options.metadonneeId) { conditions.push( - eq(indicateurValeurTable.metadonneeId, options.metadonneeId), + eq(indicateurValeurTable.metadonneeId, options.metadonneeId) ); } @@ -239,24 +244,24 @@ export default class IndicateursService { id: indicateurValeurTable.id, }); this.logger.log( - `${deletedIds.length} valeurs d'indicateurs ont été supprimées`, + `${deletedIds.length} valeurs d'indicateurs ont été supprimées` ); return { indicateurValeurIdsSupprimes: deletedIds }; } async getIndicateurValeursGroupees( options: GetIndicateursValeursRequestType, - tokenInfo: SupabaseJwtPayload, + tokenInfo: SupabaseJwtPayload ): Promise { await this.authService.verifieAccesAuxCollectivites( tokenInfo, [options.collectiviteId], - NiveauAcces.LECTURE, + NiveauAcces.LECTURE ); const indicateurValeurs = await this.getIndicateursValeurs(options); const indicateurValeursSeules = indicateurValeurs.map( - (v) => v.indicateur_valeur, + (v) => v.indicateur_valeur ); const initialDefinitionsAcc: { [key: string]: IndicateurDefinitionType } = {}; @@ -269,21 +274,21 @@ export default class IndicateursService { v.indicateur_definition; } return acc; - }, initialDefinitionsAcc), + }, initialDefinitionsAcc) ) as IndicateurDefinitionType[]; } else { uniqueIndicateurDefinitions = await this.getReferentielIndicateurDefinitions( - options.identifiantsReferentiel, + options.identifiantsReferentiel ); options.identifiantsReferentiel.forEach((identifiant) => { if ( !uniqueIndicateurDefinitions.find( - (d) => d.identifiantReferentiel === identifiant, + (d) => d.identifiantReferentiel === identifiant ) ) { this.logger.warn( - `Définition de l'indicateur avec l'identifiant référentiel ${identifiant} introuvable`, + `Définition de l'indicateur avec l'identifiant référentiel ${identifiant} introuvable` ); } }); @@ -312,7 +317,7 @@ export default class IndicateursService { v.indicateur_source_metadonnee; } return acc; - }, initialMetadonneesAcc), + }, initialMetadonneesAcc) ) as IndicateurSourceMetadonneeType[]; const indicateurValeurGroupeesParSource = @@ -320,14 +325,16 @@ export default class IndicateursService { indicateurValeursSeules, uniqueIndicateurDefinitions, uniqueIndicateurMetadonnees, - false, + false ); return { indicateurs: indicateurValeurGroupeesParSource }; } async getReferentielIndicateurDefinitions(identifiantsReferentiel: string[]) { this.logger.log( - `Récupération des définitions des indicateurs ${identifiantsReferentiel.join(',')}`, + `Récupération des définitions des indicateurs ${identifiantsReferentiel.join( + ',' + )}` ); const definitions = await this.databaseService.db .select() @@ -335,8 +342,8 @@ export default class IndicateursService { .where( inArray( indicateurDefinitionTable.identifiantReferentiel, - identifiantsReferentiel, - ), + identifiantsReferentiel + ) ); this.logger.log(`${definitions.length} définitions trouvées`); return definitions; @@ -344,7 +351,7 @@ export default class IndicateursService { async upsertIndicateurValeurs( indicateurValeurs: CreateIndicateurValeurType[], - tokenInfo?: SupabaseJwtPayload, + tokenInfo?: SupabaseJwtPayload ): Promise { if (tokenInfo) { const collectiviteIds = [ @@ -353,7 +360,7 @@ export default class IndicateursService { await this.authService.verifieAccesAuxCollectivites( tokenInfo, collectiviteIds, - NiveauAcces.EDITION, + NiveauAcces.EDITION ); if (tokenInfo.role === SupabaseRole.AUTHENTICATED && tokenInfo.sub) { @@ -365,7 +372,7 @@ export default class IndicateursService { } this.logger.log( - `Upsert des ${indicateurValeurs.length} valeurs des indicateurs pour l'utilisateur ${tokenInfo?.sub} (role ${tokenInfo?.role})`, + `Upsert des ${indicateurValeurs.length} valeurs des indicateurs pour l'utilisateur ${tokenInfo?.sub} (role ${tokenInfo?.role})` ); // On doit distinguer les valeurs avec et sans métadonnées car la clause d'unicité est différente (onConflictDoUpdate) const [indicateurValeursAvecMetadonnees, indicateurValeursSansMetadonnees] = @@ -374,13 +381,17 @@ export default class IndicateursService { const indicateurValeursResultat: IndicateurValeurType[] = []; if (indicateurValeursAvecMetadonnees.length) { this.logger.log( - `Upsert des ${indicateurValeursAvecMetadonnees.length} valeurs avec métadonnées des indicateurs ${[ + `Upsert des ${ + indicateurValeursAvecMetadonnees.length + } valeurs avec métadonnées des indicateurs ${[ ...new Set( - indicateurValeursAvecMetadonnees.map((v) => v.indicateurId), + indicateurValeursAvecMetadonnees.map((v) => v.indicateurId) ), - ].join( - ',', - )} pour les collectivités ${[...new Set(indicateurValeursAvecMetadonnees.map((v) => v.collectiviteId))].join(',')}`, + ].join(',')} pour les collectivités ${[ + ...new Set( + indicateurValeursAvecMetadonnees.map((v) => v.collectiviteId) + ), + ].join(',')}` ); const indicateurValeursAvecMetadonneesResultat = await this.databaseService.db @@ -396,37 +407,41 @@ export default class IndicateursService { targetWhere: isNotNull(indicateurValeurTable.metadonneeId), set: { resultat: sql.raw( - `excluded.${indicateurValeurTable.resultat.name}`, + `excluded.${indicateurValeurTable.resultat.name}` ), resultatCommentaire: sql.raw( - `excluded.${indicateurValeurTable.resultatCommentaire.name}`, + `excluded.${indicateurValeurTable.resultatCommentaire.name}` ), objectif: sql.raw( - `excluded.${indicateurValeurTable.objectif.name}`, + `excluded.${indicateurValeurTable.objectif.name}` ), objectifCommentaire: sql.raw( - `excluded.${indicateurValeurTable.objectifCommentaire.name}`, + `excluded.${indicateurValeurTable.objectifCommentaire.name}` ), modifiedBy: sql.raw( - `excluded.${indicateurValeurTable.modifiedBy.name}`, + `excluded.${indicateurValeurTable.modifiedBy.name}` ), }, }) .returning(); indicateurValeursResultat.push( - ...indicateurValeursAvecMetadonneesResultat, + ...indicateurValeursAvecMetadonneesResultat ); } if (indicateurValeursSansMetadonnees.length) { this.logger.log( - `Upsert des ${indicateurValeursSansMetadonnees.length} valeurs sans métadonnées des indicateurs ${[ + `Upsert des ${ + indicateurValeursSansMetadonnees.length + } valeurs sans métadonnées des indicateurs ${[ ...new Set( - indicateurValeursSansMetadonnees.map((v) => v.indicateurId), + indicateurValeursSansMetadonnees.map((v) => v.indicateurId) ), - ].join( - ',', - )} pour les collectivités ${[...new Set(indicateurValeursSansMetadonnees.map((v) => v.collectiviteId))].join(',')}`, + ].join(',')} pour les collectivités ${[ + ...new Set( + indicateurValeursSansMetadonnees.map((v) => v.collectiviteId) + ), + ].join(',')}` ); const indicateurValeursSansMetadonneesResultat = await this.databaseService.db @@ -441,39 +456,43 @@ export default class IndicateursService { targetWhere: isNull(indicateurValeurTable.metadonneeId), set: { resultat: sql.raw( - `excluded.${indicateurValeurTable.resultat.name}`, + `excluded.${indicateurValeurTable.resultat.name}` ), resultatCommentaire: sql.raw( - `excluded.${indicateurValeurTable.resultatCommentaire.name}`, + `excluded.${indicateurValeurTable.resultatCommentaire.name}` ), objectif: sql.raw( - `excluded.${indicateurValeurTable.objectif.name}`, + `excluded.${indicateurValeurTable.objectif.name}` ), objectifCommentaire: sql.raw( - `excluded.${indicateurValeurTable.objectifCommentaire.name}`, + `excluded.${indicateurValeurTable.objectifCommentaire.name}` ), modifiedBy: sql.raw( - `excluded.${indicateurValeurTable.modifiedBy.name}`, + `excluded.${indicateurValeurTable.modifiedBy.name}` ), }, }) .returning(); indicateurValeursResultat.push( - ...indicateurValeursSansMetadonneesResultat, + ...indicateurValeursSansMetadonneesResultat ); } return indicateurValeursResultat; } dedoublonnageIndicateurValeursParSource( - indicateurValeurs: IndicateurValeurAvecMetadonnesDefinition[], + indicateurValeurs: IndicateurValeurAvecMetadonnesDefinition[] ): IndicateurValeurAvecMetadonnesDefinition[] { const initialAcc: { [key: string]: IndicateurValeurAvecMetadonnesDefinition; } = {}; const uniqueIndicateurValeurs = Object.values( indicateurValeurs.reduce((acc, v) => { - const cleUnicite = `${v.indicateur_valeur.indicateurId}_${v.indicateur_valeur.collectiviteId}_${v.indicateur_valeur.dateValeur}_${v.indicateur_source_metadonnee?.sourceId || this.NULL_SOURCE_ID}`; + const cleUnicite = `${v.indicateur_valeur.indicateurId}_${ + v.indicateur_valeur.collectiviteId + }_${v.indicateur_valeur.dateValeur}_${ + v.indicateur_source_metadonnee?.sourceId || this.NULL_SOURCE_ID + }`; if (!acc[cleUnicite]) { acc[cleUnicite] = v; } else { @@ -488,7 +507,7 @@ export default class IndicateursService { } } return acc; - }, initialAcc), + }, initialAcc) ) as IndicateurValeurAvecMetadonnesDefinition[]; return uniqueIndicateurValeurs; } @@ -496,7 +515,7 @@ export default class IndicateursService { groupeIndicateursValeursParIndicateur( indicateurValeurs: IndicateurValeurType[], indicateurDefinitions: IndicateurDefinitionType[], - commentairesNonInclus = false, + commentairesNonInclus = false ): IndicateurAvecValeursType[] { const initialDefinitionsAcc: { [key: string]: MinimalIndicateurDefinitionType; @@ -515,12 +534,12 @@ export default class IndicateursService { 'unite', 'borneMin', 'borneMax', - ], + ] ) as MinimalIndicateurDefinitionType; acc[def.id.toString()] = minimaleIndicateurDefinition; } return acc; - }, initialDefinitionsAcc), + }, initialDefinitionsAcc) ) as IndicateurDefinitionType[]; const indicateurAvecValeurs = uniqueIndicateurDefinitions.map( @@ -543,7 +562,7 @@ export default class IndicateursService { } return _.omitBy( indicateurValeurGroupee, - _.isNil, + _.isNil ) as IndicateurValeurGroupee; }); // Trie les valeurs par date @@ -555,7 +574,7 @@ export default class IndicateursService { valeurs, }; return indicateurAvecValeurs; - }, + } ); return indicateurAvecValeurs.filter((i) => i.valeurs.length > 0); } @@ -564,7 +583,7 @@ export default class IndicateursService { indicateurValeurs: IndicateurValeurType[], indicateurDefinitions: IndicateurDefinitionType[], indicateurMetadonnees: IndicateurSourceMetadonneeType[], - supprimeIndicateursSansValeurs = true, + supprimeIndicateursSansValeurs = true ): IndicateurAvecValeursParSource[] { const initialDefinitionsAcc: { [key: string]: IndicateurDefinitionType } = {}; @@ -574,7 +593,7 @@ export default class IndicateursService { acc[def.id.toString()] = def; } return acc; - }, initialDefinitionsAcc), + }, initialDefinitionsAcc) ) as IndicateurDefinitionType[]; const indicateurAvecValeurs = uniqueIndicateurDefinitions.map( @@ -593,7 +612,7 @@ export default class IndicateursService { }; return _.omitBy( indicateurValeurGroupee, - _.isNil, + _.isNil ) as IndicateurValeurGroupee; }); @@ -606,11 +625,11 @@ export default class IndicateursService { return this.NULL_SOURCE_ID; } const metadonnee = indicateurMetadonnees.find( - (m) => m.id === valeur.metadonneeId, + (m) => m.id === valeur.metadonneeId ); if (!metadonnee) { this.logger.warn( - `Metadonnée introuvable pour l'identifiant ${valeur.metadonneeId}`, + `Metadonnée introuvable pour l'identifiant ${valeur.metadonneeId}` ); return this.UNKOWN_SOURCE_ID; } else { @@ -630,7 +649,7 @@ export default class IndicateursService { valeursParSource[sourceId] = valeursParSource[sourceId].sort( (a, b) => { return a.dateValeur.localeCompare(b.dateValeur); - }, + } ); sourceMap[sourceId] = { source: sourceId, @@ -643,12 +662,12 @@ export default class IndicateursService { sources: sourceMap, }; return IndicateurAvecValeursParSource; - }, + } ); if (supprimeIndicateursSansValeurs) { return indicateurAvecValeurs.filter( - (i) => Object.keys(i.sources).length > 0, + (i) => Object.keys(i.sources).length > 0 ); } else { return indicateurAvecValeurs; diff --git a/backend/src/indicateurs/services/trajectoires-data.service.ts b/backend/src/indicateurs/services/trajectoires-data.service.ts index e5a4ce0990..e4c8b64303 100644 --- a/backend/src/indicateurs/services/trajectoires-data.service.ts +++ b/backend/src/indicateurs/services/trajectoires-data.service.ts @@ -40,7 +40,7 @@ export default class TrajectoiresDataService { 'Indicateurs manquants:'; private readonly OBJECTIF_COMMENTAIRE_REGEXP = new RegExp( - String.raw`${this.OBJECTIF_COMMENTAIRE_SOURCE}\s*(.*?)(?:\s*-\s*${this.OBJECTIF_COMMENTAIRE_INDICATEURS_MANQUANTS}\s*(.*))?$`, + String.raw`${this.OBJECTIF_COMMENTAIRE_SOURCE}\s*(.*?)(?:\s*-\s*${this.OBJECTIF_COMMENTAIRE_INDICATEURS_MANQUANTS}\s*(.*))?$` ); public readonly RARE_SOURCE_ID = 'rare'; @@ -208,7 +208,7 @@ export default class TrajectoiresDataService { private readonly collectivitesService: CollectivitesService, private readonly indicateursService: IndicateursService, private readonly indicateurSourcesService: IndicateurSourcesService, - private readonly authService: AuthService, + private readonly authService: AuthService ) {} async getTrajectoireIndicateursMetadonnees(): Promise { @@ -217,30 +217,36 @@ export default class TrajectoiresDataService { this.indicateurSourceMetadonnee = await this.indicateurSourcesService.getIndicateurSourceMetadonnee( this.SNBC_SOURCE.id, - this.SNBC_SOURCE_METADONNEES.dateVersion, + this.SNBC_SOURCE_METADONNEES.dateVersion ); if (!this.indicateurSourceMetadonnee) { this.logger.log( - `Création de la metadonnée pour la source ${this.SNBC_SOURCE.id} et la date ${this.SNBC_SOURCE_METADONNEES.dateVersion.toISOString()}`, + `Création de la metadonnée pour la source ${ + this.SNBC_SOURCE.id + } et la date ${this.SNBC_SOURCE_METADONNEES.dateVersion.toISOString()}` ); await this.indicateurSourcesService.upsertIndicateurSource( - this.SNBC_SOURCE, + this.SNBC_SOURCE ); this.indicateurSourceMetadonnee = await this.indicateurSourcesService.createIndicateurSourceMetadonnee( - this.SNBC_SOURCE_METADONNEES, + this.SNBC_SOURCE_METADONNEES ); } } this.logger.log( - `La metadonnée pour la source ${this.SNBC_SOURCE.id} et la date ${this.SNBC_SOURCE_METADONNEES.dateVersion.toISOString()} existe avec l'identifiant ${this.indicateurSourceMetadonnee.id}`, + `La metadonnée pour la source ${ + this.SNBC_SOURCE.id + } et la date ${this.SNBC_SOURCE_METADONNEES.dateVersion.toISOString()} existe avec l'identifiant ${ + this.indicateurSourceMetadonnee.id + }` ); return this.indicateurSourceMetadonnee; } getObjectifCommentaire( - donneesCalculTrajectoire: DonneesCalculTrajectoireARemplirType, + donneesCalculTrajectoire: DonneesCalculTrajectoireARemplirType ): string { const identifiantsManquants = [ ...donneesCalculTrajectoire.emissions_ges @@ -253,11 +259,14 @@ export default class TrajectoiresDataService { let commentaitre = `${this.OBJECTIF_COMMENTAIRE_SOURCE} ${donneesCalculTrajectoire.source}`; if (identifiantsManquants.length) { - commentaitre += ` - ${this.OBJECTIF_COMMENTAIRE_INDICATEURS_MANQUANTS} ${identifiantsManquants.join(', ')}`; + commentaitre += ` - ${ + this.OBJECTIF_COMMENTAIRE_INDICATEURS_MANQUANTS + } ${identifiantsManquants.join(', ')}`; } return commentaitre; } + extractSourceIdentifiantManquantsFromCommentaire(commentaire: string): { source: string; identifiants_referentiel_manquants: string[]; @@ -284,20 +293,20 @@ export default class TrajectoiresDataService { */ async getValeursPourCalculTrajectoire( collectiviteId: number, - forceDonneesCollectivite?: boolean, + forceDonneesCollectivite?: boolean ): Promise { // Récupère les valeurs des indicateurs d'émission pour l'année 2015 (valeur directe ou interpolation) const source = forceDonneesCollectivite ? this.indicateursService.NULL_SOURCE_ID : this.RARE_SOURCE_ID; this.logger.log( - `Récupération des données d'émission GES et de consommation pour la collectivité ${collectiviteId} depuis la source ${source}`, + `Récupération des données d'émission GES et de consommation pour la collectivité ${collectiviteId} depuis la source ${source}` ); const indicateurValeursEmissionsGes = await this.indicateursService.getIndicateursValeurs({ collectiviteId: collectiviteId, identifiantsReferentiel: _.flatten( - this.SNBC_EMISSIONS_GES_IDENTIFIANTS_REFERENTIEL, + this.SNBC_EMISSIONS_GES_IDENTIFIANTS_REFERENTIEL ), sources: [source], }); @@ -305,7 +314,7 @@ export default class TrajectoiresDataService { // Construit le tableau de valeurs à insérer dans le fichier Spreadsheet const donneesEmissionsGes = this.getValeursARemplirPourIdentifiants( this.SNBC_EMISSIONS_GES_IDENTIFIANTS_REFERENTIEL, - indicateurValeursEmissionsGes, + indicateurValeursEmissionsGes ); // Récupère les valeurs des indicateurs de consommation finale pour l'année 2015 (valeur directe ou interpolation) @@ -313,7 +322,7 @@ export default class TrajectoiresDataService { await this.indicateursService.getIndicateursValeurs({ collectiviteId: collectiviteId, identifiantsReferentiel: _.flatten( - this.SNBC_CONSOMMATIONS_IDENTIFIANTS_REFERENTIEL, + this.SNBC_CONSOMMATIONS_IDENTIFIANTS_REFERENTIEL ), sources: [source], }); @@ -321,7 +330,7 @@ export default class TrajectoiresDataService { // Construit le tableau de valeurs à insérer dans le fichier Spreadsheet const donneesConsommationsFinales = this.getValeursARemplirPourIdentifiants( this.SNBC_CONSOMMATIONS_IDENTIFIANTS_REFERENTIEL, - indicateurValeursConsommationsFinales, + indicateurValeursConsommationsFinales ); // Récupère les valeurs des indicateurs de sequestration pour l'année 2015 (valeur directe ou interpolation) @@ -329,7 +338,7 @@ export default class TrajectoiresDataService { await this.indicateursService.getIndicateursValeurs({ collectiviteId: collectiviteId, identifiantsReferentiel: _.flatten( - this.SNBC_SEQUESTRATION_IDENTIFIANTS_REFERENTIEL, + this.SNBC_SEQUESTRATION_IDENTIFIANTS_REFERENTIEL ), sources: [source], }); @@ -337,7 +346,7 @@ export default class TrajectoiresDataService { // Construit le tableau de valeurs à insérer dans le fichier Spreadsheet const donneesSequestration = this.getValeursARemplirPourIdentifiants( this.SNBC_SEQUESTRATION_IDENTIFIANTS_REFERENTIEL, - indicateurValeursSequestration, + indicateurValeursSequestration ); return { source: source, @@ -353,7 +362,7 @@ export default class TrajectoiresDataService { */ getValeursARemplirPourIdentifiants( identifiantsReferentiel: string[][], - indicateurValeurs: IndicateurValeurAvecMetadonnesDefinition[], + indicateurValeurs: IndicateurValeurAvecMetadonnesDefinition[] ): DonneesARemplirResultType { const valeursARemplir: DonneesARemplirValeurType[] = []; const identifiantsReferentielManquants: string[] = []; @@ -371,14 +380,14 @@ export default class TrajectoiresDataService { indicateurValeur.indicateur_definition?.identifiantReferentiel === identifiant && indicateurValeur.indicateur_valeur.resultat !== null && - indicateurValeur.indicateur_valeur.resultat !== undefined, + indicateurValeur.indicateur_valeur.resultat !== undefined ); const identifiantIndicateurValeur2015 = identifiantIndicateurValeurs.find( (indicateurValeur) => indicateurValeur.indicateur_valeur.dateValeur === - this.SNBC_DATE_REFERENCE, + this.SNBC_DATE_REFERENCE ); if ( identifiantIndicateurValeur2015 && @@ -409,7 +418,7 @@ export default class TrajectoiresDataService { } } else { const interpolationResultat = this.getInterpolationValeur( - identifiantIndicateurValeurs.map((v) => v.indicateur_valeur), + identifiantIndicateurValeurs.map((v) => v.indicateur_valeur) ); if (!interpolationResultat.valeur) { @@ -503,11 +512,11 @@ export default class TrajectoiresDataService { } verificationDonneesARemplirSuffisantes( - donnees: DonneesCalculTrajectoireARemplirType, + donnees: DonneesCalculTrajectoireARemplirType ): boolean { const { emissions_ges, consommations_finales } = donnees; const valeurEmissionGesValides = emissions_ges.valeurs.filter( - (v) => v.valeur !== null, + (v) => v.valeur !== null ).length; const valeurConsommationFinalesValides = consommations_finales.valeurs.filter((v) => v.valeur !== null).length; @@ -526,13 +535,13 @@ export default class TrajectoiresDataService { request: VerificationTrajectoireRequestType, tokenInfo: SupabaseJwtPayload, epci?: EpciType, - forceRecuperationDonnees = false, + forceRecuperationDonnees = false ): Promise { // Vérification des droits await this.authService.verifieAccesAuxCollectivites( tokenInfo, [request.collectivite_id], - NiveauAcces.EDITION, + NiveauAcces.EDITION ); const response: VerificationDonneesSNBCResult = { @@ -546,7 +555,7 @@ export default class TrajectoiresDataService { if (!epci) { // Vérifie si la collectivité est une commune : const collectivite = await this.collectivitesService.getCollectivite( - request.collectivite_id, + request.collectivite_id ); if (collectivite.commune || !collectivite.epci) { response.status = VerificationDonneesSNBCStatus.COMMUNE_NON_SUPPORTEE; @@ -579,11 +588,11 @@ export default class TrajectoiresDataService { const premierCommentaire = response.valeurs[0].objectifCommentaire; const sourceIdentifiantManquants = this.extractSourceIdentifiantManquantsFromCommentaire( - premierCommentaire || '', + premierCommentaire || '' ); response.source_donnees_entree = sourceIdentifiantManquants?.source || ''; this.logger.log( - `Source des données SNBC déjà calculées : ${response.source_donnees_entree}`, + `Source des données SNBC déjà calculées : ${response.source_donnees_entree}` ); response.indentifiants_referentiel_manquants_donnees_entree = sourceIdentifiantManquants?.identifiants_referentiel_manquants || []; @@ -600,13 +609,13 @@ export default class TrajectoiresDataService { !isNil(request.force_utilisation_donnees_collectivite) ? request.force_utilisation_donnees_collectivite : response.source_donnees_entree === - this.indicateursService.NULL_SOURCE_ID - ? true - : false, + this.indicateursService.NULL_SOURCE_ID + ? true + : false ); const donneesSuffisantes = this.verificationDonneesARemplirSuffisantes( - donneesCalculTrajectoireARemplir, + donneesCalculTrajectoireARemplir ); response.donnees_entree = donneesCalculTrajectoireARemplir; // si oui, retourne 'pret a calculer' @@ -624,13 +633,13 @@ export default class TrajectoiresDataService { async deleteTrajectoireSnbc( collectiviteId: number, snbcMetadonneesId?: number, - tokenInfo?: SupabaseJwtPayload, + tokenInfo?: SupabaseJwtPayload ): Promise { if (!snbcMetadonneesId) { const indicateurSourceMetadonnee = await this.indicateurSourcesService.getIndicateurSourceMetadonnee( this.SNBC_SOURCE.id, - this.SNBC_SOURCE_METADONNEES.dateVersion, + this.SNBC_SOURCE_METADONNEES.dateVersion ); if (indicateurSourceMetadonnee) { snbcMetadonneesId = indicateurSourceMetadonnee.id; @@ -639,7 +648,7 @@ export default class TrajectoiresDataService { if (!snbcMetadonneesId) { throw new InternalServerErrorException( - `Impossible de trouver l'identifiant de la metadonnée SNBC`, + `Impossible de trouver l'identifiant de la metadonnée SNBC` ); } @@ -648,7 +657,7 @@ export default class TrajectoiresDataService { await this.authService.verifieAccesAuxCollectivites( tokenInfo, [collectiviteId], - NiveauAcces.EDITION, + NiveauAcces.EDITION ); } diff --git a/backend/src/indicateurs/services/trajectoires-spreadsheet.service.ts b/backend/src/indicateurs/services/trajectoires-spreadsheet.service.ts index ca7199f32b..68f25b2b17 100644 --- a/backend/src/indicateurs/services/trajectoires-spreadsheet.service.ts +++ b/backend/src/indicateurs/services/trajectoires-spreadsheet.service.ts @@ -31,6 +31,7 @@ import TrajectoiresDataService from './trajectoires-data.service'; export default class TrajectoiresSpreadsheetService { private readonly logger = new Logger(TrajectoiresSpreadsheetService.name); private readonly TRAJECTOIRE_GROUPEMENT = 'trajectoire'; + constructor( private readonly configService: ConfigurationService, private readonly indicateurSourcesService: IndicateurSourcesService, @@ -130,7 +131,7 @@ export default class TrajectoiresSpreadsheetService { indicateurDefinitions, (definition) => definition.identifiantReferentiel?.startsWith( - this.trajectoiresDataService.CONSOMMATIONS_IDENTIFIANTS_PREFIX, + this.trajectoiresDataService.CONSOMMATIONS_IDENTIFIANTS_PREFIX ) || false ); @@ -141,7 +142,7 @@ export default class TrajectoiresSpreadsheetService { indicateurEmissionsSequestrationDefinitions, (definition) => definition.identifiantReferentiel?.startsWith( - this.trajectoiresDataService.SEQUESTRATION_IDENTIFIANTS_PREFIX, + this.trajectoiresDataService.SEQUESTRATION_IDENTIFIANTS_PREFIX ) || false ); @@ -340,7 +341,7 @@ export default class TrajectoiresSpreadsheetService { indicateurResultatDefinitions, (definition) => definition.identifiantReferentiel?.startsWith( - this.trajectoiresDataService.CONSOMMATIONS_IDENTIFIANTS_PREFIX, + this.trajectoiresDataService.CONSOMMATIONS_IDENTIFIANTS_PREFIX ) || false ); @@ -351,7 +352,7 @@ export default class TrajectoiresSpreadsheetService { indicateurResultatSequestrationEmissionsDefinitions, (definition) => definition.identifiantReferentiel?.startsWith( - this.trajectoiresDataService.SEQUESTRATION_IDENTIFIANTS_PREFIX, + this.trajectoiresDataService.SEQUESTRATION_IDENTIFIANTS_PREFIX ) || false ); diff --git a/backend/src/indicateurs/services/trajectoires-xlsx.service.ts b/backend/src/indicateurs/services/trajectoires-xlsx.service.ts index 56867720fd..9a8d44e437 100644 --- a/backend/src/indicateurs/services/trajectoires-xlsx.service.ts +++ b/backend/src/indicateurs/services/trajectoires-xlsx.service.ts @@ -29,7 +29,7 @@ export default class TrajectoiresXlsxService { constructor( private readonly configService: BackendConfigurationService, private readonly sheetService: SheetService, - private readonly trajectoiresDataService: TrajectoiresDataService, + private readonly trajectoiresDataService: TrajectoiresDataService ) { this.initXlsxBuffers(); } @@ -45,18 +45,18 @@ export default class TrajectoiresXlsxService { async downloadModeleTrajectoireSnbc( request: ModeleTrajectoireTelechargementRequestType, res: Response, - next: NextFunction, + next: NextFunction ) { try { if (!this.getIdentifiantXlsxCalcul()) { throw new InternalServerErrorException( - "L'identifiant du Xlsx pour le calcul des trajectoires SNBC est manquant", + "L'identifiant du Xlsx pour le calcul des trajectoires SNBC est manquant" ); } await this.initXlsxBuffers(request.force_recuperation_xlsx); const nomFichier = await this.sheetService.getFileName( - this.getIdentifiantXlsxCalcul(), + this.getIdentifiantXlsxCalcul() ); // Set the output file name. @@ -73,10 +73,10 @@ export default class TrajectoiresXlsxService { async initXlsxBuffers(forceRecuperation?: boolean) { if (!this.xlsxModeleBuffer || forceRecuperation) { this.logger.log( - `Récupération des données du fichier Xlsx de calcul ${this.getIdentifiantXlsxCalcul()} (force: ${forceRecuperation})`, + `Récupération des données du fichier Xlsx de calcul ${this.getIdentifiantXlsxCalcul()} (force: ${forceRecuperation})` ); this.xlsxModeleBuffer = await this.sheetService.getFileData( - this.getIdentifiantXlsxCalcul(), + this.getIdentifiantXlsxCalcul() ); if (this.xlsxModeleBuffer) { @@ -85,7 +85,7 @@ export default class TrajectoiresXlsxService { this.xlsxVideBuffer = await this.generationXlsxDonneesSubstituees( nouveauBuffer, { siren: null }, - null, + null ); } else { // Null in test @@ -100,7 +100,7 @@ export default class TrajectoiresXlsxService { await this.initXlsxBuffers(); } else { this.logger.log( - `Utilisation du buffer du fichier Xlsx de calcul déjà chargé`, + `Utilisation du buffer du fichier Xlsx de calcul déjà chargé` ); } return Buffer.from(this.xlsxModeleBuffer!); @@ -115,7 +115,7 @@ export default class TrajectoiresXlsxService { siren: { siren: number | null; }, - valeurIndicateurs: DonneesCalculTrajectoireARemplirType | null, + valeurIndicateurs: DonneesCalculTrajectoireARemplirType | null ): Promise { // Utilisation de xlsx-template car: // https://github.com/SheetJS/sheetjs/issues/347: sheetjs does not keep style @@ -142,7 +142,7 @@ export default class TrajectoiresXlsxService { emissionGesSequestrationConsommationsSubstitionValeurs[ cleSubstitution ] = 0; - }, + } ); this.trajectoiresDataService.SNBC_SEQUESTRATION_IDENTIFIANTS_REFERENTIEL.forEach( (identifiants) => { @@ -150,7 +150,7 @@ export default class TrajectoiresXlsxService { emissionGesSequestrationConsommationsSubstitionValeurs[ cleSubstitution ] = 0; - }, + } ); this.trajectoiresDataService.SNBC_CONSOMMATIONS_IDENTIFIANTS_REFERENTIEL.forEach( (identifiants) => { @@ -158,32 +158,32 @@ export default class TrajectoiresXlsxService { emissionGesSequestrationConsommationsSubstitionValeurs[ cleSubstitution ] = 0; - }, + } ); valeurIndicateurs?.emissions_ges.valeurs.forEach((valeur) => { const cleSubstitution = this.getXlsxCleSubstitution( - valeur.identifiants_referentiel, + valeur.identifiants_referentiel ); emissionGesSequestrationConsommationsSubstitionValeurs[cleSubstitution] = (valeur.valeur || 0) / 1000; }); valeurIndicateurs?.sequestrations.valeurs.forEach((valeur) => { const cleSubstitution = this.getXlsxCleSubstitution( - valeur.identifiants_referentiel, + valeur.identifiants_referentiel ); emissionGesSequestrationConsommationsSubstitionValeurs[cleSubstitution] = ((valeur.valeur || 0) * -1) / 1000; }); valeurIndicateurs?.consommations_finales.valeurs.forEach((valeur) => { const cleSubstitution = this.getXlsxCleSubstitution( - valeur.identifiants_referentiel, + valeur.identifiants_referentiel ); emissionGesSequestrationConsommationsSubstitionValeurs[cleSubstitution] = valeur.valeur || 0; }); template.substitute( emissionsGesSequestrationConsommationsSheetName, - emissionGesSequestrationConsommationsSubstitionValeurs, + emissionGesSequestrationConsommationsSubstitionValeurs ); // TODO: type it @@ -206,12 +206,12 @@ export default class TrajectoiresXlsxService { request: CollectiviteRequestType, tokenInfo: SupabaseJwtPayload, res: Response, - next: NextFunction, + next: NextFunction ) { try { if (!this.getIdentifiantXlsxCalcul()) { throw new InternalServerErrorException( - "L'identifiant du Xlsx pour le calcul des trajectoires SNBC est manquant", + "L'identifiant du Xlsx pour le calcul des trajectoires SNBC est manquant" ); } @@ -220,7 +220,7 @@ export default class TrajectoiresXlsxService { request, tokenInfo, undefined, - true, + true ); if ( @@ -229,7 +229,7 @@ export default class TrajectoiresXlsxService { !resultatVerification.epci ) { throw new UnprocessableEntityException( - `Le calcul de trajectoire SNBC peut uniquement être effectué pour un EPCI.`, + `Le calcul de trajectoire SNBC peut uniquement être effectué pour un EPCI.` ); } else if ( resultatVerification.status === @@ -243,14 +243,16 @@ export default class TrajectoiresXlsxService { .identifiants_referentiel_manquants || []), ]; throw new UnprocessableEntityException( - `Les indicateurs suivants n'ont pas de valeur pour l'année 2015 ou avec une interpolation possible : ${identifiantsReferentielManquants.join(', ')}, impossible de calculer la trajectoire SNBC.`, + `Les indicateurs suivants n'ont pas de valeur pour l'année 2015 ou avec une interpolation possible : ${identifiantsReferentielManquants.join( + ', ' + )}, impossible de calculer la trajectoire SNBC.` ); } const epci = resultatVerification.epci; const nomFichier = this.getNomFichierTrajectoire(epci); this.logger.log( - `Récupération des données du fichier ${this.getIdentifiantXlsxCalcul()}`, + `Récupération des données du fichier ${this.getIdentifiantXlsxCalcul()}` ); const xlsxBuffer = await this.getXlsxModeleBuffer(); @@ -261,7 +263,7 @@ export default class TrajectoiresXlsxService { const generatedData = await this.generationXlsxDonneesSubstituees( xlsxBuffer, sirenData, - resultatVerification.donnees_entree, + resultatVerification.donnees_entree ); this.logger.log(`Renvoi du fichier Xlsx généré`); diff --git a/backend/src/main.ts b/backend/src/main.ts index 7397fd99d5..989eda3b68 100644 --- a/backend/src/main.ts +++ b/backend/src/main.ts @@ -53,4 +53,5 @@ async function bootstrap() { await app.listen(port); } + bootstrap(); diff --git a/backend/src/panier/controllers/action-impact.controllers.ts b/backend/src/panier/controllers/action-impact.controllers.ts index 94d4e4e27f..487de0b15e 100644 --- a/backend/src/panier/controllers/action-impact.controllers.ts +++ b/backend/src/panier/controllers/action-impact.controllers.ts @@ -12,10 +12,10 @@ export class ActionImpactController { @Get('details') @ApiResponse({ type: ActionImpactDetailsClass }) async fetchActionImpactDetails( - @Query() request: { actionImpactId: number }, + @Query() request: { actionImpactId: number } ): Promise { return this.indicateurService.getActionImpactDetails( - request.actionImpactId, + request.actionImpactId ); } } diff --git a/backend/src/panier/controllers/panier.controllers.ts b/backend/src/panier/controllers/panier.controllers.ts index cf0e13ceda..076b2778bd 100644 --- a/backend/src/panier/controllers/panier.controllers.ts +++ b/backend/src/panier/controllers/panier.controllers.ts @@ -28,17 +28,17 @@ export class PanierController { constructor( private readonly panierService: PanierService, - private readonly planFromPanierService: PlanFromPanierService, + private readonly planFromPanierService: PlanFromPanierService ) {} @Get('') @ApiResponse({ type: PanierClass }) async panierFromLanding( - @Query() request: CollectiviteRequestType, + @Query() request: CollectiviteRequestType ): Promise { if (request.collectivite_id) { this.logger.log( - `Récupération du panier de la collectivité ${request.collectivite_id}.`, + `Récupération du panier de la collectivité ${request.collectivite_id}.` ); } else { this.logger.log(`Création d'un nouveau panier.`); @@ -48,86 +48,86 @@ export class PanierController { @Post('action_impact') async addActionToPanier( - @Body() request: ActionInPanierRequestClass, + @Body() request: ActionInPanierRequestClass ): Promise { this.logger.log( - `Ajoute l'action ${request.actionImpactId} au panier ${request.panierId}`, + `Ajoute l'action ${request.actionImpactId} au panier ${request.panierId}` ); await this.panierService.addActionImpact( request.actionImpactId, - request.panierId, + request.panierId ); } @Delete('action_impact') async removeActionFromPanier( - @Query() request: ActionInPanierRequestClass, + @Query() request: ActionInPanierRequestClass ): Promise { this.logger.log( - `Enlève l'action ${request.actionImpactId} au panier ${request.panierId}`, + `Enlève l'action ${request.actionImpactId} au panier ${request.panierId}` ); await this.panierService.removeActionImpact( request.actionImpactId, - request.panierId, + request.panierId ); } @Put('action_impact/statut') async setActionStatut( - @Body() request: ActionInPanierStatutRequestClass, + @Body() request: ActionInPanierStatutRequestClass ): Promise { this.logger.log( - `Change le statut de l'action ${request.actionImpactId} dans le panier ${request.panierId} par ${request.categorieId}`, + `Change le statut de l'action ${request.actionImpactId} dans le panier ${request.panierId} par ${request.categorieId}` ); await this.panierService.setActionImpactCategorie( request.actionImpactId, request.panierId, - request.categorieId || null, + request.categorieId || null ); } @Get('contenu') @ApiResponse({ type: PanierCompletClass }) async fetchPanier( - @Query() request: GetPanierCompletRequestClass, + @Query() request: GetPanierCompletRequestClass ): Promise { this.logger.log(`Récupération du contenu du panier ${request.panierId}.`); return this.panierService.getPanierComplet( request.panierId, request.thematiquesIds, request.niveauxBudget, - request.niveauxTemps, + request.niveauxTemps ); } @Post('contenu') async createPlanFromPanier( @Body() request: CreatePlanFromPanierRequestClass, - @TokenInfo() tokenInfo: SupabaseJwtPayload, + @TokenInfo() tokenInfo: SupabaseJwtPayload ): Promise { if (request.planId) { this.logger.log( - `Ajoute le contenu du panier ${request.panierId} au plan ${request.planId} pour la collectivité ${request.collectiviteId}`, + `Ajoute le contenu du panier ${request.panierId} au plan ${request.planId} pour la collectivité ${request.collectiviteId}` ); } else { this.logger.log( - `Cree un plan à partir du panier ${request.panierId} pour la collectivité ${request.collectiviteId}`, + `Cree un plan à partir du panier ${request.panierId} pour la collectivité ${request.collectiviteId}` ); } return await this.planFromPanierService.addPlanFromPanier( tokenInfo, request.collectiviteId, request.panierId, - request.planId, + request.planId ); } @Put('directus') async majPanierFromDirectus( - @TokenInfo() tokenInfo: SupabaseJwtPayload, + @TokenInfo() tokenInfo: SupabaseJwtPayload ): Promise { this.logger.log( - `Met à jour les contenus du panier dans l'app par rapport au contenu dans Directus.`, + `Met à jour les contenus du panier dans l'app par rapport au contenu dans Directus.` ); await this.panierService.majPanierFromDirectus(tokenInfo); } diff --git a/backend/src/panier/models/action-impact-action.table.ts b/backend/src/panier/models/action-impact-action.table.ts index 60de4790bb..139430a2fd 100644 --- a/backend/src/panier/models/action-impact-action.table.ts +++ b/backend/src/panier/models/action-impact-action.table.ts @@ -18,7 +18,7 @@ export const actionImpactActionTable = pgTable( return { pk: primaryKey({ columns: [table.actionImpactId, table.actionId] }), }; - }, + } ); export type ActionImpactActionType = InferSelectModel< diff --git a/backend/src/panier/models/action-impact-banatic-competence.table.ts b/backend/src/panier/models/action-impact-banatic-competence.table.ts index 9fd4665ad8..4576428c79 100644 --- a/backend/src/panier/models/action-impact-banatic-competence.table.ts +++ b/backend/src/panier/models/action-impact-banatic-competence.table.ts @@ -20,5 +20,5 @@ export const actionImpactBanaticCompetenceTable = pgTable( name: 'action_impact_banatic_competence_pkey', }), }; - }, + } ); diff --git a/backend/src/panier/models/action-impact-cateorie-fnv.table.ts b/backend/src/panier/models/action-impact-cateorie-fnv.table.ts index 38eb64c3ca..a1b6498c9e 100644 --- a/backend/src/panier/models/action-impact-cateorie-fnv.table.ts +++ b/backend/src/panier/models/action-impact-cateorie-fnv.table.ts @@ -18,5 +18,5 @@ export const actionImpactCategorieFNVTable = pgTable( columns: [table.actionImpactId, table.categorieFnvId], }), }; - }, + } ); diff --git a/backend/src/panier/models/action-impact-effet-attendu.table.ts b/backend/src/panier/models/action-impact-effet-attendu.table.ts index 51e52527e2..5f65e001e0 100644 --- a/backend/src/panier/models/action-impact-effet-attendu.table.ts +++ b/backend/src/panier/models/action-impact-effet-attendu.table.ts @@ -19,7 +19,7 @@ export const actionImpactEffetAttenduTable = pgTable( columns: [table.actionImpactId, table.effetAttenduId], }), }; - }, + } ); export type ActionImpactEffetAttenduType = InferSelectModel< typeof actionImpactEffetAttenduTable diff --git a/backend/src/panier/models/action-impact-fourchette-budgetaire.table.ts b/backend/src/panier/models/action-impact-fourchette-budgetaire.table.ts index f23e30170b..5f3d93d577 100644 --- a/backend/src/panier/models/action-impact-fourchette-budgetaire.table.ts +++ b/backend/src/panier/models/action-impact-fourchette-budgetaire.table.ts @@ -6,7 +6,7 @@ export const actionImpactFourchetteBudgetaireTable = pgTable( { niveau: serial('niveau').primaryKey(), nom: text('nom').notNull(), - }, + } ); export type ActionImpactFourchetteBudgetaireType = InferSelectModel< typeof actionImpactFourchetteBudgetaireTable diff --git a/backend/src/panier/models/action-impact-indicateur.table.ts b/backend/src/panier/models/action-impact-indicateur.table.ts index 7a5bcaea00..fc44a9a54d 100644 --- a/backend/src/panier/models/action-impact-indicateur.table.ts +++ b/backend/src/panier/models/action-impact-indicateur.table.ts @@ -19,7 +19,7 @@ export const actionImpactIndicateurTable = pgTable( columns: [table.actionImpactId, table.indicateurId], }), }; - }, + } ); export type ActionImpactIndicateurType = InferSelectModel< typeof actionImpactIndicateurTable diff --git a/backend/src/panier/models/action-impact-panier.table.ts b/backend/src/panier/models/action-impact-panier.table.ts index 36463e7908..00ec85075b 100644 --- a/backend/src/panier/models/action-impact-panier.table.ts +++ b/backend/src/panier/models/action-impact-panier.table.ts @@ -16,5 +16,5 @@ export const actionImpactPanierTable = pgTable( return { pk: primaryKey({ columns: [table.panierId, table.actionId] }), }; - }, + } ); diff --git a/backend/src/panier/models/action-impact-partenaire.table.ts b/backend/src/panier/models/action-impact-partenaire.table.ts index ad4eb79aef..87add19f28 100644 --- a/backend/src/panier/models/action-impact-partenaire.table.ts +++ b/backend/src/panier/models/action-impact-partenaire.table.ts @@ -18,5 +18,5 @@ export const actionImpactPartenaireTable = pgTable( columns: [table.actionImpactId, table.partenaireId], }), }; - }, + } ); diff --git a/backend/src/panier/models/action-impact-sous-thematique.table.ts b/backend/src/panier/models/action-impact-sous-thematique.table.ts index 932ac55764..239e2315d4 100644 --- a/backend/src/panier/models/action-impact-sous-thematique.table.ts +++ b/backend/src/panier/models/action-impact-sous-thematique.table.ts @@ -19,7 +19,7 @@ export const actionImpactSousThematiqueTable = pgTable( columns: [table.actionImpactId, table.sousThematiqueId], }), }; - }, + } ); export type ActionImpactSousThematiqueType = InferSelectModel< diff --git a/backend/src/panier/models/action-impact-statut.table.ts b/backend/src/panier/models/action-impact-statut.table.ts index 0d9e5d85db..a3d6ba8446 100644 --- a/backend/src/panier/models/action-impact-statut.table.ts +++ b/backend/src/panier/models/action-impact-statut.table.ts @@ -1,10 +1,4 @@ -import { - integer, - pgTable, - primaryKey, - text, - uuid, -} from 'drizzle-orm/pg-core'; +import { integer, pgTable, primaryKey, text, uuid } from 'drizzle-orm/pg-core'; import { actionImpactTable } from './action-impact.table'; import { InferSelectModel } from 'drizzle-orm'; import { panierTable } from './panier.table'; @@ -28,11 +22,11 @@ export const actionImpactStatutTable = pgTable( return { pk: primaryKey({ columns: [table.panierId, table.actionId] }), }; - }, + } ); export type ActionImpactStatutType = InferSelectModel< typeof actionImpactStatutTable >; export const actionImpactStatutSchema = createSelectSchema( - actionImpactStatutTable, + actionImpactStatutTable ); diff --git a/backend/src/panier/models/action-impact-temps-de-mise-en-oeuvre.table.ts b/backend/src/panier/models/action-impact-temps-de-mise-en-oeuvre.table.ts index adb15b40b7..cc1d0f78c2 100644 --- a/backend/src/panier/models/action-impact-temps-de-mise-en-oeuvre.table.ts +++ b/backend/src/panier/models/action-impact-temps-de-mise-en-oeuvre.table.ts @@ -5,5 +5,5 @@ export const actionImpactTempsDeMiseEnOeuvreTable = pgTable( { niveau: serial('niveau').primaryKey(), nom: text('nom').notNull(), - }, + } ); diff --git a/backend/src/panier/models/action-impact-thematique.table.ts b/backend/src/panier/models/action-impact-thematique.table.ts index e1649c7229..a8f4e44a2c 100644 --- a/backend/src/panier/models/action-impact-thematique.table.ts +++ b/backend/src/panier/models/action-impact-thematique.table.ts @@ -20,7 +20,7 @@ export const actionImpactThematiqueTable = pgTable( columns: [table.actionImpactId, table.thematiqueId], }), }; - }, + } ); export type ActionImpactThematiqueType = InferSelectModel< diff --git a/backend/src/panier/models/action-impact.table.ts b/backend/src/panier/models/action-impact.table.ts index 5d33360afd..c0b8a0edce 100644 --- a/backend/src/panier/models/action-impact.table.ts +++ b/backend/src/panier/models/action-impact.table.ts @@ -7,8 +7,14 @@ import { serial, text, } from 'drizzle-orm/pg-core'; -import { thematiqueSchema, ThematiqueType } from '../../taxonomie/models/thematique.table'; -import { categorieFNVSchema, CategorieFNVType } from '../../taxonomie/models/categorie-fnv.table'; +import { + thematiqueSchema, + ThematiqueType, +} from '../../taxonomie/models/thematique.table'; +import { + categorieFNVSchema, + CategorieFNVType, +} from '../../taxonomie/models/categorie-fnv.table'; import { actionImpactTempsDeMiseEnOeuvreTable } from './action-impact-temps-de-mise-en-oeuvre.table'; import { actionImpactFourchetteBudgetaireTable } from './action-impact-fourchette-budgetaire.table'; import { actionImpactTierTable } from './action-impact-tier.table'; @@ -90,5 +96,5 @@ export const actionImpactDetailsSchema = actionImpactTransformeSchema.extend({ }); export class ActionImpactDetailsClass extends createZodDto( - actionImpactDetailsSchema, + actionImpactDetailsSchema ) {} diff --git a/backend/src/panier/models/action-in-panier-statut.request.ts b/backend/src/panier/models/action-in-panier-statut.request.ts index 8d5f7873d5..bd5c233319 100644 --- a/backend/src/panier/models/action-in-panier-statut.request.ts +++ b/backend/src/panier/models/action-in-panier-statut.request.ts @@ -4,16 +4,18 @@ import { actionInPanierRequestSchema } from './action-in-panier.request'; import { z } from 'zod'; export const ActionInPanierStatutRequestSchema = extendApi( - actionInPanierRequestSchema.extend({ - categorieId: z - .string() - .optional() - .openapi({ description: `Identifiant du statut` }), - }).openapi({ - title: `Statut d'une action à impact dans un panier.`, - }), + actionInPanierRequestSchema + .extend({ + categorieId: z + .string() + .optional() + .openapi({ description: `Identifiant du statut` }), + }) + .openapi({ + title: `Statut d'une action à impact dans un panier.`, + }) ); export class ActionInPanierStatutRequestClass extends createZodDto( - ActionInPanierStatutRequestSchema, + ActionInPanierStatutRequestSchema ) {} diff --git a/backend/src/panier/models/action-in-panier.request.ts b/backend/src/panier/models/action-in-panier.request.ts index 74929ec55b..f19e7c965e 100644 --- a/backend/src/panier/models/action-in-panier.request.ts +++ b/backend/src/panier/models/action-in-panier.request.ts @@ -12,9 +12,9 @@ export const actionInPanierRequestSchema = extendApi( }) .openapi({ title: 'Action à impact dans un panier.', - }), + }) ); export class ActionInPanierRequestClass extends createZodDto( - actionInPanierRequestSchema, + actionInPanierRequestSchema ) {} diff --git a/backend/src/panier/models/create-plan-from-panier.request.ts b/backend/src/panier/models/create-plan-from-panier.request.ts index 18c591c7c3..2223e60a0c 100644 --- a/backend/src/panier/models/create-plan-from-panier.request.ts +++ b/backend/src/panier/models/create-plan-from-panier.request.ts @@ -15,9 +15,9 @@ export const createPlanFromPanierRequestSchema = extendApi( }) .openapi({ title: 'Panier à transformer en plan pour une collectivité.', - }), + }) ); export class CreatePlanFromPanierRequestClass extends createZodDto( - createPlanFromPanierRequestSchema, -) {} \ No newline at end of file + createPlanFromPanierRequestSchema +) {} diff --git a/backend/src/panier/models/get-panier-complet.request.ts b/backend/src/panier/models/get-panier-complet.request.ts index d4ca21ba12..def8cf742b 100644 --- a/backend/src/panier/models/get-panier-complet.request.ts +++ b/backend/src/panier/models/get-panier-complet.request.ts @@ -19,9 +19,9 @@ export const getPanierCompletRequestSchema = extendApi( .openapi({ title: 'Identifiant du panier et filtres à appliquer sur le contenu à récupérer.', - }), + }) ); export class GetPanierCompletRequestClass extends createZodDto( - getPanierCompletRequestSchema, -) {} \ No newline at end of file + getPanierCompletRequestSchema +) {} diff --git a/backend/src/panier/models/get-panier-complet.response.ts b/backend/src/panier/models/get-panier-complet.response.ts index 4a1b56fde8..6a587e2c17 100644 --- a/backend/src/panier/models/get-panier-complet.response.ts +++ b/backend/src/panier/models/get-panier-complet.response.ts @@ -30,7 +30,7 @@ export const actionImpactStateSchema = extendApi( isinpanier: z.boolean(), statut: actionImpactStatutSchema.nullable(), thematiques: z.array(thematiqueSchema), - }), + }) ); export type PanierCompletType = @@ -50,7 +50,7 @@ export const panierCompletSchema = extendApi( }) .openapi({ title: `Panier d'une collectivité avec son contenu.`, - }), + }) ); export class PanierCompletClass extends createZodDto(panierCompletSchema) {} diff --git a/backend/src/panier/models/panier.table.ts b/backend/src/panier/models/panier.table.ts index 1876b47a9d..dcd868d2a7 100644 --- a/backend/src/panier/models/panier.table.ts +++ b/backend/src/panier/models/panier.table.ts @@ -19,7 +19,7 @@ export const panierTable = pgTable('panier', { .defaultNow(), createdBy: uuid('created_by'), // TODO references auth.users collectiviteId: integer('collectivite_id').references( - () => collectiviteTable.id, + () => collectiviteTable.id ), collectivitePreset: integer('collectivite_preset') .unique() @@ -28,7 +28,7 @@ export const panierTable = pgTable('panier', { .notNull() .defaultNow(), private: boolean('private').generatedAlwaysAs( - (): SQL => sql`(${panierTable.collectiviteId} is not null)`, + (): SQL => sql`(${panierTable.collectiviteId} is not null)` ), }); export type PanierType = InferSelectModel; diff --git a/backend/src/panier/services/action-impact.service.ts b/backend/src/panier/services/action-impact.service.ts index 3197c84673..f454ce5cde 100644 --- a/backend/src/panier/services/action-impact.service.ts +++ b/backend/src/panier/services/action-impact.service.ts @@ -30,10 +30,10 @@ export default class ActionImpactService { * @return l'action détaillé */ async getActionImpactDetails( - actionImpactId: number, + actionImpactId: number ): Promise { this.logger.log( - `Récupération du détail de l'action à impact ${actionImpactId}`, + `Récupération du détail de l'action à impact ${actionImpactId}` ); const actions = await this.databaseService.db .select({ @@ -47,19 +47,19 @@ export default class ActionImpactService { .from(actionImpactTable) .leftJoin( actionImpactThematiqueTable, - eq(actionImpactTable.id, actionImpactThematiqueTable.actionImpactId), + eq(actionImpactTable.id, actionImpactThematiqueTable.actionImpactId) ) .leftJoin( thematiqueTable, - eq(actionImpactThematiqueTable.thematiqueId, thematiqueTable.id), + eq(actionImpactThematiqueTable.thematiqueId, thematiqueTable.id) ) .leftJoin( actionImpactCategorieFNVTable, - eq(actionImpactTable.id, actionImpactCategorieFNVTable.actionImpactId), + eq(actionImpactTable.id, actionImpactCategorieFNVTable.actionImpactId) ) .leftJoin( categorieFNVTable, - eq(actionImpactCategorieFNVTable.categorieFnvId, categorieFNVTable.id), + eq(actionImpactCategorieFNVTable.categorieFnvId, categorieFNVTable.id) ) .where(eq(actionImpactTable.id, actionImpactId)) .limit(1); @@ -73,7 +73,7 @@ export default class ActionImpactService { */ async majActionImpactFromDirectus( action: ActionImpact, - datas: Datas, + datas: Datas ): Promise { // Upsert action_impact const actionToSave = { @@ -97,7 +97,7 @@ export default class ActionImpactService { description: sql.raw(`excluded.description`), fourchetteBudgetaire: sql.raw(`excluded.fourchette_budgetaire`), descriptionComplementaire: sql.raw( - `excluded.description_complementaire`, + `excluded.description_complementaire` ), tempsDeMiseEnOeuvre: sql.raw(`excluded.temps_de_mise_en_oeuvre`), ressourcesExternes: sql.raw(`excluded.ressources_externes`), @@ -106,7 +106,7 @@ export default class ActionImpactService { }, }); Logger.log( - `Action ${action.id} - Sauvegarde de l''action à impact : réussi`, + `Action ${action.id} - Sauvegarde de l''action à impact : réussi` ); // Upsert action_impact_thematique await this.databaseService.db @@ -121,11 +121,11 @@ export default class ActionImpactService { }); if (!query) { Logger.log( - `Action ${action.id} - Sauvegarde de la thématique ${thematique.thematique_id} : échec`, + `Action ${action.id} - Sauvegarde de la thématique ${thematique.thematique_id} : échec` ); } else { Logger.log( - `Action ${action.id} - Sauvegarde de la thématique ${thematique.thematique_id} : réussi`, + `Action ${action.id} - Sauvegarde de la thématique ${thematique.thematique_id} : réussi` ); } } @@ -138,7 +138,7 @@ export default class ActionImpactService { for (const thematique of action.sous_thematiques) { // Récupère le nom de la sous thématique dans directus const thematiqueDirectus = datas.sousThematiquesDirectus.find( - (t) => t.id === thematique.sous_thematique_id, + (t) => t.id === thematique.sous_thematique_id ); if (thematiqueDirectus) { // Fait le lien avec la sous thématique en BDD via le nom @@ -152,11 +152,11 @@ export default class ActionImpactService { }); if (!query) { Logger.log( - `Action ${action.id} - Sauvegarde de la sous thématique ${thematiqueBDD.id} : échec`, + `Action ${action.id} - Sauvegarde de la sous thématique ${thematiqueBDD.id} : échec` ); } else { Logger.log( - `Action ${action.id} - Sauvegarde de la sous thématique ${thematiqueBDD.id} : réussi`, + `Action ${action.id} - Sauvegarde de la sous thématique ${thematiqueBDD.id} : réussi` ); } } @@ -171,7 +171,7 @@ export default class ActionImpactService { for (const indicateur of action.indicateurs) { // Récupère l'indentifiant BDD de l'indicateur à partir de son identifiant référentiel const indicateurId = datas.indicateurs.get( - indicateur.indicateur_predefini_id!, + indicateur.indicateur_predefini_id! )?.id; if (indicateurId) { const query = await this.databaseService.db @@ -182,11 +182,11 @@ export default class ActionImpactService { }); if (!query) { Logger.log( - `Action ${action.id} - Sauvegarde de l'indicateur ${indicateur.indicateur_predefini_id} : échec`, + `Action ${action.id} - Sauvegarde de l'indicateur ${indicateur.indicateur_predefini_id} : échec` ); } else { Logger.log( - `Action ${action.id} - Sauvegarde de l'indicateur ${indicateur.indicateur_predefini_id} : réussi`, + `Action ${action.id} - Sauvegarde de l'indicateur ${indicateur.indicateur_predefini_id} : réussi` ); } } @@ -204,7 +204,7 @@ export default class ActionImpactService { effetAttenduId: effet.action_impact_effet_attendu_id, }); Logger.log( - `Action ${action.id} - Sauvegarde de l'effet attendu ${effet.action_impact_effet_attendu_id} réussi`, + `Action ${action.id} - Sauvegarde de l'effet attendu ${effet.action_impact_effet_attendu_id} réussi` ); } @@ -221,11 +221,11 @@ export default class ActionImpactService { }); if (!query) { Logger.log( - `Action ${action.id} - Sauvegarde du partenaire ${partenaire.action_impact_partenaire_id} : échec`, + `Action ${action.id} - Sauvegarde du partenaire ${partenaire.action_impact_partenaire_id} : échec` ); } else { Logger.log( - `Action ${action.id} - Sauvegarde du partenaire ${partenaire.action_impact_partenaire_id} : réussi`, + `Action ${action.id} - Sauvegarde du partenaire ${partenaire.action_impact_partenaire_id} : réussi` ); } } @@ -243,11 +243,11 @@ export default class ActionImpactService { }); if (!query) { Logger.log( - `Action ${action.id} - Sauvegarde de l'action référentiel ${actionRef.action_referentiel_id} : échec`, + `Action ${action.id} - Sauvegarde de l'action référentiel ${actionRef.action_referentiel_id} : échec` ); } else { Logger.log( - `Action ${action.id} - Sauvegarde de l'action référentiel ${actionRef.action_referentiel_id} : réussi`, + `Action ${action.id} - Sauvegarde de l'action référentiel ${actionRef.action_referentiel_id} : réussi` ); } } @@ -265,11 +265,11 @@ export default class ActionImpactService { }); if (!query) { Logger.log( - `Action ${action.id} - Sauvegarde de la compétence ${competence.competence_code} : échec`, + `Action ${action.id} - Sauvegarde de la compétence ${competence.competence_code} : échec` ); } else { Logger.log( - `Action ${action.id} - Sauvegarde de la compétence ${competence.competence_code} : réussi`, + `Action ${action.id} - Sauvegarde de la compétence ${competence.competence_code} : réussi` ); } } diff --git a/backend/src/panier/services/panier.service.ts b/backend/src/panier/services/panier.service.ts index 6a542c987c..91b788234a 100644 --- a/backend/src/panier/services/panier.service.ts +++ b/backend/src/panier/services/panier.service.ts @@ -41,7 +41,7 @@ export default class PanierService { private readonly directusService: DirectusService, private readonly thematiqueService: ThematiqueService, private readonly indicateurService: IndicateursService, - private readonly actionImpactService: ActionImpactService, + private readonly actionImpactService: ActionImpactService ) {} /** @@ -61,9 +61,9 @@ export default class PanierService { isNull(panierTable.collectiviteId), gt( panierTable.createdAt, - sql.raw(`current_timestamp - interval '1 month'`), - ), - ), + sql.raw(`current_timestamp - interval '1 month'`) + ) + ) ); panier = paniers.length > 0 ? paniers[0] : null; } @@ -106,8 +106,8 @@ export default class PanierService { .where( and( eq(actionImpactPanierTable.actionId, actionId), - eq(actionImpactPanierTable.panierId, panierId), - ), + eq(actionImpactPanierTable.panierId, panierId) + ) ); this.panierGateway.emitPanierUpdate(panierId); } @@ -121,11 +121,11 @@ export default class PanierService { async setActionImpactCategorie( actionId: number, panierId: string, - categorieId: string | null, + categorieId: string | null ): Promise { if (categorieId) { this.logger.log( - `Remplacement par le statut ${categorieId} sur l'action ${actionId} pour le panier ${panierId}`, + `Remplacement par le statut ${categorieId} sur l'action ${actionId} pour le panier ${panierId}` ); await this.databaseService.db .insert(actionImpactStatutTable) @@ -143,15 +143,15 @@ export default class PanierService { }); } else { this.logger.log( - `Retrait de la catégorie sur l'action ${actionId} pour le panier ${panierId}`, + `Retrait de la catégorie sur l'action ${actionId} pour le panier ${panierId}` ); await this.databaseService.db .delete(actionImpactCategorieTable) .where( and( eq(actionImpactPanierTable.actionId, actionId), - eq(actionImpactPanierTable.panierId, panierId), - ), + eq(actionImpactPanierTable.panierId, panierId) + ) ); } this.panierGateway.emitPanierUpdate(panierId); @@ -169,7 +169,7 @@ export default class PanierService { panierId: string, thematiqueIds: number[], niveauxBudget: number[], - niveauxTemps: number[], + niveauxTemps: number[] ): Promise { const where = []; @@ -180,7 +180,7 @@ export default class PanierService { if (niveauxBudget && niveauxBudget.length > 0) { where.push(isNotNull(actionImpactTable.fourchetteBudgetaire)); where.push( - inArray(actionImpactTable.fourchetteBudgetaire, niveauxBudget), + inArray(actionImpactTable.fourchetteBudgetaire, niveauxBudget) ); } if (niveauxTemps && niveauxTemps.length > 0) { @@ -200,59 +200,56 @@ export default class PanierService { actionImpactStatutTable, and( eq(actionImpactTable.id, actionImpactStatutTable.actionId), - eq(actionImpactStatutTable.panierId, panierId), - ), + eq(actionImpactStatutTable.panierId, panierId) + ) ) .leftJoin( actionImpactThematiqueTable, - eq(actionImpactTable.id, actionImpactThematiqueTable.actionImpactId), + eq(actionImpactTable.id, actionImpactThematiqueTable.actionImpactId) ) .leftJoin( thematiqueTable, - eq(actionImpactThematiqueTable.thematiqueId, thematiqueTable.id), + eq(actionImpactThematiqueTable.thematiqueId, thematiqueTable.id) ) .leftJoin( actionImpactPanierTable, and( eq(actionImpactPanierTable.actionId, actionImpactTable.id), - eq(actionImpactPanierTable.panierId, panierId), - ), + eq(actionImpactPanierTable.panierId, panierId) + ) ) .where(and(...where)); return Object.values( - actions.reduce( - (acc, row) => { - const actionId = row.action.id; + actions.reduce((acc, row) => { + const actionId = row.action.id; - if (!acc[actionId]) { - acc[actionId] = { - action: { - ...row.action, - rex: Array.isArray(row.action.rex) ? row.action.rex : [], - subventionsMobilisables: Array.isArray( - row.action.subventionsMobilisables, - ) - ? row.action.subventionsMobilisables - : [], - ressourcesExternes: Array.isArray(row.action.ressourcesExternes) - ? row.action.ressourcesExternes - : [], - }, - isinpanier: !!row.isInPanier, - statut: row.statut || null, - thematiques: [], - }; - } + if (!acc[actionId]) { + acc[actionId] = { + action: { + ...row.action, + rex: Array.isArray(row.action.rex) ? row.action.rex : [], + subventionsMobilisables: Array.isArray( + row.action.subventionsMobilisables + ) + ? row.action.subventionsMobilisables + : [], + ressourcesExternes: Array.isArray(row.action.ressourcesExternes) + ? row.action.ressourcesExternes + : [], + }, + isinpanier: !!row.isInPanier, + statut: row.statut || null, + thematiques: [], + }; + } - if (row.thematique) { - acc[actionId].thematiques.push(row.thematique); - } + if (row.thematique) { + acc[actionId].thematiques.push(row.thematique); + } - return acc; - }, - {} as Record, - ), + return acc; + }, {} as Record) ); } @@ -268,26 +265,26 @@ export default class PanierService { panierId: string, thematiqueIds: number[], niveauxBudget: number[], - niveauxTemps: number[], + niveauxTemps: number[] ): Promise { const paniersResult = await this.databaseService.db .select() .from(panierTable) .leftJoin( actionImpactPanierTable, - eq(actionImpactPanierTable.panierId, panierTable.id), + eq(actionImpactPanierTable.panierId, panierTable.id) ) .leftJoin( actionImpactTable, - eq(actionImpactTable.id, actionImpactPanierTable.actionId), + eq(actionImpactTable.id, actionImpactPanierTable.actionId) ) .leftJoin( actionImpactThematiqueTable, - eq(actionImpactTable.id, actionImpactThematiqueTable.actionImpactId), + eq(actionImpactTable.id, actionImpactThematiqueTable.actionImpactId) ) .leftJoin( thematiqueTable, - eq(actionImpactThematiqueTable.thematiqueId, thematiqueTable.id), + eq(actionImpactThematiqueTable.thematiqueId, thematiqueTable.id) ) .where(eq(panierTable.id, panierId)); @@ -296,45 +293,42 @@ export default class PanierService { panierId, thematiqueIds, niveauxBudget, - niveauxTemps, + niveauxTemps ); return { ...paniersResult[0].panier, contenu: Object.values( paniersResult .filter((f) => f.action_impact !== null) - .reduce( - (acc, row) => { - const actionId = row.action_impact!.id; + .reduce((acc, row) => { + const actionId = row.action_impact!.id; - if (!acc[actionId]) { - acc[actionId] = { - ...row.action_impact!, - rex: Array.isArray(row.action_impact!.rex) - ? row.action_impact!.rex - : [], - subventionsMobilisables: Array.isArray( - row.action_impact!.subventionsMobilisables, - ) - ? row.action_impact!.subventionsMobilisables - : [], - ressourcesExternes: Array.isArray( - row.action_impact!.ressourcesExternes, - ) - ? row.action_impact!.ressourcesExternes - : [], - thematiques: [], - }; - } + if (!acc[actionId]) { + acc[actionId] = { + ...row.action_impact!, + rex: Array.isArray(row.action_impact!.rex) + ? row.action_impact!.rex + : [], + subventionsMobilisables: Array.isArray( + row.action_impact!.subventionsMobilisables + ) + ? row.action_impact!.subventionsMobilisables + : [], + ressourcesExternes: Array.isArray( + row.action_impact!.ressourcesExternes + ) + ? row.action_impact!.ressourcesExternes + : [], + thematiques: [], + }; + } - if (row.thematique) { - acc[actionId].thematiques.push(row.thematique); - } + if (row.thematique) { + acc[actionId].thematiques.push(row.thematique); + } - return acc; - }, - {} as Record, - ), + return acc; + }, {} as Record) ), states: actionsFiltrees, }; diff --git a/backend/src/panier/services/plan-from-panier.service.ts b/backend/src/panier/services/plan-from-panier.service.ts index 9c594d0163..a75ce59c88 100644 --- a/backend/src/panier/services/plan-from-panier.service.ts +++ b/backend/src/panier/services/plan-from-panier.service.ts @@ -81,7 +81,7 @@ export default class PlanFromPanierService { private readonly ficheService: FicheService, private readonly documentService: DocumentService, private readonly authService: AuthService, - private readonly brevoService: BrevoService, + private readonly brevoService: BrevoService ) {} /** @@ -96,12 +96,12 @@ export default class PlanFromPanierService { tokenInfo: SupabaseJwtPayload, collectiviteId: number, panierId: string, - planId?: number, + planId?: number ): Promise { // Vérifie les droits await this.authService.verifieAccesRestreintCollectivite( tokenInfo, - collectiviteId, + collectiviteId ); let axeId; if (!planId) { @@ -138,137 +138,128 @@ export default class PlanFromPanierService { * @return les actions à impact et leurs informations liées */ private async getActionsFromPanier( - panierId: string, + panierId: string ): Promise { const result = await this.databaseService.db .select() .from(actionImpactTable) .innerJoin( actionImpactPanierTable, - eq(actionImpactTable.id, actionImpactPanierTable.actionId), + eq(actionImpactTable.id, actionImpactPanierTable.actionId) ) .leftJoin( actionImpactThematiqueTable, - eq(actionImpactTable.id, actionImpactThematiqueTable.actionImpactId), + eq(actionImpactTable.id, actionImpactThematiqueTable.actionImpactId) ) .leftJoin( actionImpactSousThematiqueTable, - eq( - actionImpactTable.id, - actionImpactSousThematiqueTable.actionImpactId, - ), + eq(actionImpactTable.id, actionImpactSousThematiqueTable.actionImpactId) ) .leftJoin( actionImpactFourchetteBudgetaireTable, eq( actionImpactTable.fourchetteBudgetaire, - actionImpactFourchetteBudgetaireTable.niveau, - ), + actionImpactFourchetteBudgetaireTable.niveau + ) ) .leftJoin( actionImpactIndicateurTable, - eq(actionImpactTable.id, actionImpactIndicateurTable.actionImpactId), + eq(actionImpactTable.id, actionImpactIndicateurTable.actionImpactId) ) .leftJoin( actionImpactEffetAttenduTable, - eq(actionImpactTable.id, actionImpactEffetAttenduTable.actionImpactId), + eq(actionImpactTable.id, actionImpactEffetAttenduTable.actionImpactId) ) .leftJoin( actionImpactActionTable, - eq(actionImpactTable.id, actionImpactActionTable.actionImpactId), + eq(actionImpactTable.id, actionImpactActionTable.actionImpactId) ) .leftJoin( actionImpactPartenaireTable, - eq(actionImpactTable.id, actionImpactPartenaireTable.actionImpactId), + eq(actionImpactTable.id, actionImpactPartenaireTable.actionImpactId) ) .leftJoin( panierPartenaireTable, - eq(panierPartenaireTable.id, actionImpactPartenaireTable.partenaireId), + eq(panierPartenaireTable.id, actionImpactPartenaireTable.partenaireId) ) .leftJoin( actionImpactStatutTable, and( eq(actionImpactTable.id, actionImpactStatutTable.actionId), - eq( - actionImpactPanierTable.panierId, - actionImpactStatutTable.panierId, - ), - ), + eq(actionImpactPanierTable.panierId, actionImpactStatutTable.panierId) + ) ) .leftJoin( actionImpactCategorieTable, - eq(actionImpactStatutTable.categorieId, actionImpactCategorieTable.id), + eq(actionImpactStatutTable.categorieId, actionImpactCategorieTable.id) ) .where(eq(actionImpactPanierTable.panierId, panierId)); // Transforme le résultat de la requête en des objects // de type addPlanFromPanierResult plus facile à manipuler return Object.values( - result.reduce( - (acc, row) => { - const actionId = row.action_impact.id; + result.reduce((acc, row) => { + const actionId = row.action_impact.id; - if (!acc[actionId]) { - acc[actionId] = { - action_impact: { - ...row.action_impact, - rex: Array.isArray(row.action_impact.rex) - ? row.action_impact.rex - : [], - subventionsMobilisables: Array.isArray( - row.action_impact.subventionsMobilisables, - ) - ? row.action_impact.subventionsMobilisables - : [], - ressourcesExternes: Array.isArray( - row.action_impact.ressourcesExternes, - ) - ? row.action_impact.ressourcesExternes - : [], - }, - action_impact_thematique: [], - action_impact_sous_thematique: [], - action_impact_indicateur: [], - action_impact_effet_attendu: [], - action_impact_action: [], - panier_partenaire: [], - action_impact_fourchette_budgetaire: - row.action_impact_fourchette_budgetaire, - action_impact_categorie: row.action_impact_categorie, - }; - } + if (!acc[actionId]) { + acc[actionId] = { + action_impact: { + ...row.action_impact, + rex: Array.isArray(row.action_impact.rex) + ? row.action_impact.rex + : [], + subventionsMobilisables: Array.isArray( + row.action_impact.subventionsMobilisables + ) + ? row.action_impact.subventionsMobilisables + : [], + ressourcesExternes: Array.isArray( + row.action_impact.ressourcesExternes + ) + ? row.action_impact.ressourcesExternes + : [], + }, + action_impact_thematique: [], + action_impact_sous_thematique: [], + action_impact_indicateur: [], + action_impact_effet_attendu: [], + action_impact_action: [], + panier_partenaire: [], + action_impact_fourchette_budgetaire: + row.action_impact_fourchette_budgetaire, + action_impact_categorie: row.action_impact_categorie, + }; + } - if (row.action_impact_thematique) { - acc[actionId].action_impact_thematique.push( - row.action_impact_thematique, - ); - } - if (row.action_impact_sous_thematique) { - acc[actionId].action_impact_sous_thematique.push( - row.action_impact_sous_thematique, - ); - } - if (row.action_impact_indicateur) { - acc[actionId].action_impact_indicateur.push( - row.action_impact_indicateur, - ); - } - if (row.action_impact_effet_attendu) { - acc[actionId].action_impact_effet_attendu.push( - row.action_impact_effet_attendu, - ); - } - if (row.action_impact_action) { - acc[actionId].action_impact_action.push(row.action_impact_action); - } - if (row.panier_partenaire) { - acc[actionId].panier_partenaire.push(row.panier_partenaire); - } + if (row.action_impact_thematique) { + acc[actionId].action_impact_thematique.push( + row.action_impact_thematique + ); + } + if (row.action_impact_sous_thematique) { + acc[actionId].action_impact_sous_thematique.push( + row.action_impact_sous_thematique + ); + } + if (row.action_impact_indicateur) { + acc[actionId].action_impact_indicateur.push( + row.action_impact_indicateur + ); + } + if (row.action_impact_effet_attendu) { + acc[actionId].action_impact_effet_attendu.push( + row.action_impact_effet_attendu + ); + } + if (row.action_impact_action) { + acc[actionId].action_impact_action.push(row.action_impact_action); + } + if (row.panier_partenaire) { + acc[actionId].panier_partenaire.push(row.panier_partenaire); + } - return acc; - }, - {} as Record, - ), + return acc; + }, {} as Record) ); } @@ -281,7 +272,7 @@ export default class PlanFromPanierService { private async addFicheFromActionImpact( collectiviteId: number, axeId: number, - action: actionsFromPanier, + action: actionsFromPanier ) { // On créé une fiche const ficheId = await this.ficheService.createFiche({ @@ -313,7 +304,7 @@ export default class PlanFromPanierService { for (const thematique of action.action_impact_sous_thematique) { await this.ficheService.addSousThematique( ficheId, - thematique.sousThematiqueId, + thematique.sousThematiqueId ); } } @@ -334,7 +325,7 @@ export default class PlanFromPanierService { for (const actionRef of action.action_impact_action) { await this.ficheService.addActionReferentiel( ficheId, - actionRef.actionId, + actionRef.actionId ); } } @@ -345,7 +336,7 @@ export default class PlanFromPanierService { await this.documentService.createLienAnnexe( ficheId, ressource as lienType, - collectiviteId, + collectiviteId ); } } @@ -354,7 +345,7 @@ export default class PlanFromPanierService { await this.documentService.createLienAnnexe( ficheId, ressource as lienType, - collectiviteId, + collectiviteId ); } } @@ -365,7 +356,7 @@ export default class PlanFromPanierService { await this.ficheService.addPartenaireByNom( ficheId, partenaire.nom, - collectiviteId, + collectiviteId ); } } @@ -392,7 +383,7 @@ export default class PlanFromPanierService { // Vérifie si le contact appartient déjà à la liste if ( !contactJson.listIds.includes( - BrevoLists.ID_LIST_BREVO_ONBOARDING_PAI, + BrevoLists.ID_LIST_BREVO_ONBOARDING_PAI ) ) { emails.push(email); @@ -402,7 +393,7 @@ export default class PlanFromPanierService { if (contactJson.listIds.includes(listId)) { await this.brevoService.removeContactsFromList(emails, listId); this.logger.log( - 'remove contact' + contactJson.email + ' from list ' + listId, + 'remove contact' + contactJson.email + ' from list ' + listId ); } } diff --git a/backend/src/referentiel/models/action-definition.table.ts b/backend/src/referentiel/models/action-definition.table.ts index 7544aab123..44b63c5462 100644 --- a/backend/src/referentiel/models/action-definition.table.ts +++ b/backend/src/referentiel/models/action-definition.table.ts @@ -18,7 +18,7 @@ export const actionCategorieEnum = pgEnum('action_categorie', [ ]); export const actionIdVarchar = varchar('action_id', { length: 30 }); export const actionIdReference = actionIdVarchar.references( - () => actionDefinitionTable.actionId, + () => actionDefinitionTable.actionId ); export const actionDefinitionTable = pgTable('action_definition', { @@ -52,7 +52,7 @@ export const actionDefinitionSchema = createSelectSchema(actionDefinitionTable); export const actionDefinitionSeulementIdObligatoireSchema = actionDefinitionSchema.partial(); export const createActionDefinitionSchema = createInsertSchema( - actionDefinitionTable, + actionDefinitionTable ); export type ActionDefinitionAvecParentType = Pick< @@ -60,5 +60,5 @@ export type ActionDefinitionAvecParentType = Pick< 'actionId' > & Partial & { - parentActionId: string | null; -}; + parentActionId: string | null; + }; diff --git a/backend/src/referentiel/models/action-relation.table.ts b/backend/src/referentiel/models/action-relation.table.ts index 55af19e12b..4c3cfc924d 100644 --- a/backend/src/referentiel/models/action-relation.table.ts +++ b/backend/src/referentiel/models/action-relation.table.ts @@ -13,7 +13,7 @@ export const actionRelationTable = pgTable('action_relation', { .notNull(), referentiel: referentielEnum('referentiel').notNull(), parent: varchar('parent', { length: 30 }).references( - () => actionDefinitionTable.actionId, + () => actionDefinitionTable.actionId ), }); diff --git a/backend/src/spreadsheets/services/sheet.service.ts b/backend/src/spreadsheets/services/sheet.service.ts index 6543a8338f..7a9cc4e3d7 100644 --- a/backend/src/spreadsheets/services/sheet.service.ts +++ b/backend/src/spreadsheets/services/sheet.service.ts @@ -9,6 +9,7 @@ import { SheetValueInputOption, SheetValueRenderOption, } from '../models/sheetoptions.models'; + const sheets = google.sheets({ version: 'v4' }); const drive = google.drive({ version: 'v3' }); diff --git a/backend/src/taxonomie/models/categorie-tag.table.ts b/backend/src/taxonomie/models/categorie-tag.table.ts index c990cd2176..8e55892e7f 100644 --- a/backend/src/taxonomie/models/categorie-tag.table.ts +++ b/backend/src/taxonomie/models/categorie-tag.table.ts @@ -1,4 +1,10 @@ -import { boolean, integer, pgTable, timestamp, uuid } from 'drizzle-orm/pg-core'; +import { + boolean, + integer, + pgTable, + timestamp, + uuid, +} from 'drizzle-orm/pg-core'; import { TagBase } from './tag.basetable'; export const categorieTagTable = pgTable('categorie_tag', { diff --git a/backend/src/taxonomie/models/financeur-tag.table.ts b/backend/src/taxonomie/models/financeur-tag.table.ts index ab2d8711e9..795ab5c031 100644 --- a/backend/src/taxonomie/models/financeur-tag.table.ts +++ b/backend/src/taxonomie/models/financeur-tag.table.ts @@ -4,7 +4,7 @@ import { TagBase } from './tag.basetable'; export const financeurTagTable = pgTable('financeur_tag', TagBase, (table) => { return { financeurTagNomCollectiviteIdKey: uniqueIndex( - 'financeur_tag_nom_collectivite_id_key', + 'financeur_tag_nom_collectivite_id_key' ).on(table.nom, table.collectiviteId), }; }); diff --git a/backend/src/taxonomie/models/partenaire-tag.table.ts b/backend/src/taxonomie/models/partenaire-tag.table.ts index 00dcecc6de..3a398f9c70 100644 --- a/backend/src/taxonomie/models/partenaire-tag.table.ts +++ b/backend/src/taxonomie/models/partenaire-tag.table.ts @@ -7,8 +7,8 @@ export const partenaireTagTable = pgTable( (table) => { return { partenaireTagNomCollectiviteIdKey: uniqueIndex( - 'partenaire_tag_nom_collectivite_id_key', + 'partenaire_tag_nom_collectivite_id_key' ).on(table.nom, table.collectiviteId), }; - }, + } ); diff --git a/backend/src/taxonomie/models/personne-tag.table.ts b/backend/src/taxonomie/models/personne-tag.table.ts index 0ae6529f5e..35ab8f23c4 100644 --- a/backend/src/taxonomie/models/personne-tag.table.ts +++ b/backend/src/taxonomie/models/personne-tag.table.ts @@ -4,7 +4,7 @@ import { TagBase } from './tag.basetable'; export const personneTagTable = pgTable('personne_tag', TagBase, (table) => { return { personneTagNomCollectiviteIdKey: uniqueIndex( - 'personne_tag_nom_collectivite_id_key', + 'personne_tag_nom_collectivite_id_key' ).on(table.nom, table.collectiviteId), }; }); diff --git a/backend/src/taxonomie/models/service-tag.table.ts b/backend/src/taxonomie/models/service-tag.table.ts index dc0eafc7e7..beed257bef 100644 --- a/backend/src/taxonomie/models/service-tag.table.ts +++ b/backend/src/taxonomie/models/service-tag.table.ts @@ -4,7 +4,7 @@ import { TagBase } from './tag.basetable'; export const serviceTagTable = pgTable('service_tag', TagBase, (table) => { return { serviceTagNomCollectiviteIdKey: uniqueIndex( - 'service_tag_nom_collectivite_id_key', + 'service_tag_nom_collectivite_id_key' ).on(table.nom, table.collectiviteId), }; }); diff --git a/backend/src/taxonomie/models/sous-thematique.table.ts b/backend/src/taxonomie/models/sous-thematique.table.ts index a7031db51b..1fe9b284da 100644 --- a/backend/src/taxonomie/models/sous-thematique.table.ts +++ b/backend/src/taxonomie/models/sous-thematique.table.ts @@ -20,9 +20,9 @@ export const sousThematiqueTable = pgTable( (table) => { return { sousThematiqueSousThematiqueThematiqueIdKey: uniqueIndex( - 'sous_thematique_sous_thematique_thematique_id_key ', + 'sous_thematique_sous_thematique_thematique_id_key ' ).on(table.sousThematique, table.thematiqueId), }; - }, + } ); export type SousThematiqueType = InferSelectModel; diff --git a/backend/src/taxonomie/models/structure-tag.table.ts b/backend/src/taxonomie/models/structure-tag.table.ts index 04ec34b379..07f065be4e 100644 --- a/backend/src/taxonomie/models/structure-tag.table.ts +++ b/backend/src/taxonomie/models/structure-tag.table.ts @@ -4,7 +4,7 @@ import { TagBase } from './tag.basetable'; export const structureTagTable = pgTable('structure_tag', TagBase, (table) => { return { structureTagNomCollectiviteIdKey: uniqueIndex( - 'structure_tag_nom_collectivite_id_key', + 'structure_tag_nom_collectivite_id_key' ).on(table.nom, table.collectiviteId), }; }); diff --git a/backend/src/taxonomie/services/panier-partenaire.service.ts b/backend/src/taxonomie/services/panier-partenaire.service.ts index d9f975ad01..43a8d18dd1 100644 --- a/backend/src/taxonomie/services/panier-partenaire.service.ts +++ b/backend/src/taxonomie/services/panier-partenaire.service.ts @@ -10,7 +10,7 @@ export default class PanierPartenaireService { constructor( private readonly databaseService: DatabaseService, - private readonly directusService: DirectusService, + private readonly directusService: DirectusService ) {} /** diff --git a/backend/src/taxonomie/services/tag.service.ts b/backend/src/taxonomie/services/tag.service.ts index 927060c25c..f9bd82c27c 100644 --- a/backend/src/taxonomie/services/tag.service.ts +++ b/backend/src/taxonomie/services/tag.service.ts @@ -25,8 +25,8 @@ export default class TagService { .where( and( eq(partenaireTagTable.nom, nom.trim()), - eq(partenaireTagTable.collectiviteId, collectiviteId), - ), + eq(partenaireTagTable.collectiviteId, collectiviteId) + ) ); tag = tags.length > 0 ? tags[0] : null; } diff --git a/backend/src/trpc.router.ts b/backend/src/trpc.router.ts index 5498475f53..37fa74f859 100644 --- a/backend/src/trpc.router.ts +++ b/backend/src/trpc.router.ts @@ -9,7 +9,7 @@ export class TrpcRouter { constructor( private readonly trpc: TrpcService, - private readonly trajectoiresRouter: TrajectoiresRouter, + private readonly trajectoiresRouter: TrajectoiresRouter ) {} appRouter = this.trpc.router({ @@ -22,7 +22,7 @@ export class TrpcRouter { `/trpc`, trpcExpress.createExpressMiddleware({ router: this.appRouter, - }), + }) ); } }