From 35fe246fcaffba6af30f23b844595e1a6fd41bed Mon Sep 17 00:00:00 2001 From: SAFINE LAGET Anis <anis.safine@beta.gouv.fr> Date: Wed, 23 Apr 2025 12:17:24 +0000 Subject: [PATCH] feat(tdb): ajoute la machine au tableau de bord des super (pub/pnm-public/camino!1686) --- packages/api/src/api/_format/etapes-types.ts | 2 +- packages/api/src/api/_format/titres-etapes.ts | 25 +- .../src/api/graphql/resolvers/_titre-etape.ts | 29 +- .../api/graphql/resolvers/titres-etapes.ts | 19 +- .../titres-demarches.test.integration.ts | 1 + .../api/graphql/titres.test.integration.ts | 4 + .../demarches.test.integration.ts.snap | 2 +- .../etapes.test.integration.ts.snap | 463 +++++++++++++ .../api/rest/activites.test.integration.ts | 1 + .../api/src/api/rest/demarches.queries.ts | 5 + .../src/api/rest/demarches.queries.types.ts | 2 + .../api/rest/demarches.test.integration.ts | 31 +- packages/api/src/api/rest/demarches.ts | 156 +++-- .../api/rest/entreprises.test.integration.ts | 15 +- .../api/rest/etape-creer.test.integration.ts | 2 + .../rest/etape-deposer.test.integration.ts | 1 + .../rest/etape-modifier.test.integration.ts | 2 + .../src/api/rest/etapes.test.integration.ts | 119 +++- packages/api/src/api/rest/etapes.ts | 344 ++++++---- packages/api/src/api/rest/format/titres.ts | 10 +- .../src/api/rest/index.test.integration.ts | 1 + .../api/rest/perimetre.test.integration.ts | 3 + packages/api/src/api/rest/rest-test-utils.ts | 8 +- .../api/src/api/rest/titre-demande.queries.ts | 35 +- .../api/rest/titre-demande.queries.types.ts | 4 +- packages/api/src/api/rest/titre-demande.ts | 4 +- packages/api/src/api/rest/titres.queries.ts | 62 +- .../api/src/api/rest/titres.queries.types.ts | 1 + .../src/api/rest/titres.test.integration.ts | 28 +- packages/api/src/api/rest/titres.ts | 20 +- .../api/src/business/check-prolongations.ts | 13 +- packages/api/src/business/daily.ts | 12 +- .../business/fill-documents-non-renseigne.ts | 31 +- .../processes/demarche-machine-id-update.ts | 51 ++ .../titres-demarches-public-update.ts | 8 +- ...titres-demarches-statut-ids-update.test.ts | 3 + .../titres-demarches-statut-ids-update.ts | 8 +- ...es-etapes-consentement.test.integration.ts | 20 +- ...-etapes-heritage-contenu-update.queries.ts | 6 + ...s-heritage-contenu-update.queries.types.ts | 1 + .../titres-etapes-heritage-contenu-update.ts | 8 +- ...es-mise-en-concurrence.test.integration.ts | 5 + .../titres-etapes-ordre-update.test.ts | 26 +- .../processes/titres-etapes-ordre-update.ts | 10 +- .../processes/titres-etapes-statut-update.ts | 8 +- .../processes/titres-phases-update.test.ts | 5 + .../titres-statut-ids-update.test.ts | 2 + .../processes/update-machine-id.queries.ts | 18 + .../update-machine-id.queries.types.ts | 17 + .../business/rules-demarches/machines.test.ts | 41 +- .../src/business/rules-demarches/machines.ts | 66 +- .../rules/titre-activites-build.test.ts | 1 + .../rules/titre-date-demande-find.test.ts | 1 + ...-demarche-annulation-date-fin-find.test.ts | 44 +- ...titre-demarche-annulation-date-fin-find.ts | 23 +- .../rules/titre-demarche-public-find.test.ts | 629 +++++++----------- .../rules/titre-demarche-public-find.ts | 23 +- .../titre-demarche-statut-id-find.test.ts | 245 ++++--- .../rules/titre-demarche-statut-id-find.ts | 31 +- .../rules/titre-etape-prop-find.test.ts | 40 +- .../business/rules/titre-phases-find.test.ts | 582 ++++++++++------ .../src/business/rules/titre-phases-find.ts | 52 +- .../rules/titre-prop-etape-find.test.ts | 193 +++--- .../api/src/business/titre-etape-update.ts | 2 + .../utils/titre-demarches-etapes-rebuild.ts | 15 +- .../business/utils/titre-etapes-sort.test.ts | 111 ++-- .../src/business/utils/titre-etapes-sort.ts | 28 +- ...g-and-relations-update.test.integration.ts | 5 +- .../titre-demarche-etat-validate.test.ts | 401 +++++------ .../titre-demarche-etat-validate.ts | 57 +- .../titre-etape-updation-validate.test.ts | 36 +- .../titre-etape-updation-validate.ts | 45 +- .../src/database/models/titres-demarches.ts | 1 + .../permissions/titres.test.integration.ts | 7 +- .../src/database/queries/titres-demarches.ts | 7 - .../database/queries/titres-etapes.queries.ts | 23 +- .../queries/titres-etapes.queries.types.ts | 2 + .../queries/titres-utilisateurs.queries.ts | 1 + .../titres-utilisateurs.queries.types.ts | 1 + ...5135645_add-column-machine-to-demarches.ts | 49 ++ packages/api/src/pg-database.ts | 17 +- .../src/tools/demarches/definitions-check.ts | 9 +- packages/api/src/tools/demarches/tde-check.ts | 12 +- .../api/src/tools/demarches/tests-creation.ts | 41 +- .../src/tools/etapes/etapes-complete-check.ts | 25 +- packages/api/src/types.ts | 2 + .../_utils/administrations-permissions.ts | 24 +- packages/api/tests/_utils/index.ts | 13 + packages/api/vitest.integration.config.ts | 4 +- packages/common/src/avisTypes.test.ts | 112 +--- packages/common/src/avisTypes.ts | 32 +- packages/common/src/demarche.test.ts | 28 +- packages/common/src/demarche.ts | 29 +- packages/common/src/machines.test.ts | 126 +++- packages/common/src/machines.ts | 108 ++- .../common/src/permissions/etape-form.test.ts | 203 +++--- packages/common/src/permissions/etape-form.ts | 80 +-- .../src/permissions/titres-demarches.test.ts | 94 ++- .../src/permissions/titres-demarches.ts | 17 +- .../src/permissions/titres-etapes.test.ts | 314 ++++----- .../common/src/permissions/titres-etapes.ts | 139 ++-- .../common/src/permissions/titres.test.ts | 18 +- packages/common/src/permissions/titres.ts | 3 +- packages/common/src/sections.test.ts | 30 +- packages/common/src/sections.ts | 13 +- .../documents.test.ts | 74 +-- .../documents.ts | 31 +- .../entrepriseDocuments.test.ts | 21 +- .../entrepriseDocuments.ts | 9 +- .../sections.test.ts | 28 +- .../sections.ts | 9 +- packages/common/src/titres.ts | 4 + packages/common/src/validators/machine.ts | 13 + .../_common/dsfr-perimetre.stories.tsx | 33 +- .../dsfr-perimetre.stories_snapshots_Big.html | 4 +- ...r-perimetre.stories_snapshots_Default.html | 4 +- ...-perimetre.stories_snapshots_Multiple.html | 4 +- ...rimetre.stories_snapshots_NoNeighbors.html | 4 +- ...e.stories_snapshots_PolygonWithLacune.html | 4 +- .../src/components/_common/dsfr-perimetre.tsx | 10 +- .../pure-super-dashboard.stories.tsx | 2 + ...ories_snapshots_TableauPleinBrouillon.html | 3 + .../dashboard/pure-super-dashboard.tsx | 14 +- .../demarche-resultat-mise-en-concurrence.tsx | 13 +- .../demarche/demarche-etape.stories.tsx | 72 +- .../components/demarche/demarche-etape.tsx | 24 +- .../src/components/demarche/demarche-map.tsx | 11 +- .../src/components/etape-edition.stories.tsx | 29 + ...ape-edition.stories_snapshots_Loading.html | 7 + ...e-edition.stories_snapshots_WithError.html | 9 + packages/ui/src/components/etape-edition.tsx | 71 +- .../entreprises-documents-edit.stories.tsx | 18 +- .../etape/entreprises-documents-edit.tsx | 8 +- .../src/components/etape/etape-api-client.ts | 1 - .../etape/etape-avis-edit.stories.tsx | 12 +- .../src/components/etape/etape-avis-edit.tsx | 15 +- .../etape/etape-documents-edit.stories.tsx | 29 +- .../components/etape/etape-documents-edit.tsx | 12 +- .../etape/etape-edit-form.stories.tsx | 39 +- .../src/components/etape/etape-edit-form.tsx | 146 ++-- .../etape/fondamentales-edit.stories.tsx | 35 +- .../components/etape/fondamentales-edit.tsx | 34 +- .../etape/perimetre-edit.stories.tsx | 27 +- .../src/components/etape/perimetre-edit.tsx | 26 +- .../etape/sections-edit.stories.tsx | 17 +- .../ui/src/components/etape/sections-edit.tsx | 10 +- packages/ui/src/components/titre.stories.tsx | 22 +- .../titre.stories_snapshots_BasseManaMod.html | 14 +- ...tre.stories_snapshots_BonEspoirOctroi.html | 150 +++-- ...ries_snapshots_BonEspoirProlongation2.html | 189 +++++- ...e.stories_snapshots_ChantepieMutation.html | 2 +- ...tre.stories_snapshots_ChantepieOctroi.html | 2 +- ...stories_snapshots_CriqueAdolpheOctroi.html | 4 +- .../titre.stories_snapshots_Lenoncourt.html | 16 +- packages/ui/src/components/titre.tsx | 97 ++- .../demarche-mise-en-concurrence.stories.tsx | 9 + .../titre/demarche-mise-en-concurrence.tsx | 21 +- .../ui/src/components/titre/phase.test.ts | 8 + .../resultat-mise-en-concurrence.stories.tsx | 256 +++---- .../titre/resultat-mise-en-concurrence.tsx | 11 +- .../src/components/titre/titre-demarche.tsx | 35 +- 161 files changed, 4512 insertions(+), 3166 deletions(-) create mode 100644 packages/api/src/api/rest/__snapshots__/etapes.test.integration.ts.snap create mode 100644 packages/api/src/business/processes/demarche-machine-id-update.ts create mode 100644 packages/api/src/business/processes/update-machine-id.queries.ts create mode 100644 packages/api/src/business/processes/update-machine-id.queries.types.ts create mode 100644 packages/api/src/knex/migrations/20250325135645_add-column-machine-to-demarches.ts create mode 100644 packages/common/src/validators/machine.ts create mode 100644 packages/ui/src/components/etape-edition.stories_snapshots_Loading.html create mode 100644 packages/ui/src/components/etape-edition.stories_snapshots_WithError.html diff --git a/packages/api/src/api/_format/etapes-types.ts b/packages/api/src/api/_format/etapes-types.ts index 4757e45cd..3b960bc51 100644 --- a/packages/api/src/api/_format/etapes-types.ts +++ b/packages/api/src/api/_format/etapes-types.ts @@ -1,9 +1,9 @@ -import { demarcheEnregistrementDemandeDateFind } from 'camino-common/src/demarche' import { ITitreEtape } from '../../types' import { DocumentType } from 'camino-common/src/static/documentsTypes' import { EtapesTypes, EtapeTypeId } from 'camino-common/src/static/etapesTypes' import { isNotNullNorUndefinedNorEmpty } from 'camino-common/src/typescript-tools' +import { demarcheEnregistrementDemandeDateFind } from '../../business/rules-demarches/machines' export const documentsTypesFormat = (documentsTypes: DocumentType[] | undefined | null, documentsTypesSpecifiques: DocumentType[] | undefined | null): DocumentType[] => { let result: DocumentType[] = [] diff --git a/packages/api/src/api/_format/titres-etapes.ts b/packages/api/src/api/_format/titres-etapes.ts index 3be455124..384b3f8df 100644 --- a/packages/api/src/api/_format/titres-etapes.ts +++ b/packages/api/src/api/_format/titres-etapes.ts @@ -11,6 +11,7 @@ import { z } from 'zod' import { Effect } from 'effect' import { CaminoError } from 'camino-common/src/zod-tools' import { zodParseEffect, ZodUnparseable } from '../../tools/fp-tools' +import { MachineInfo } from 'camino-common/src/machines' const getPerimetreFromITitreEtape = ( titreEtape: Pick< @@ -31,27 +32,11 @@ const getPerimetreFromITitreEtape = ( const apiFlattenEtapeValidator = flattenEtapeValidator.and(titreEtapeForMachineValidator.pick({ concurrence: true, hasTitreFrom: true, demarcheIdsConsentement: true })) export type ApiFlattenEtape = z.infer<typeof apiFlattenEtapeValidator> -const pasDeDemarcheOuDeTitreCharge = 'pas de démarche ou de titre chargé' as const -const pasDeDemarcheChargee = 'pas de démarche chargée' as const const pasDHeritageCharge = "pas d'héritage chargé" as const const pasDeSlug = 'pas de slug' as const -export type TitreEtapeToFlattenEtapeErrors = typeof pasDeDemarcheOuDeTitreCharge | typeof pasDeDemarcheChargee | typeof pasDHeritageCharge | typeof pasDeSlug | ZodUnparseable -export const iTitreEtapeToFlattenEtape = (titreEtape: ITitreEtape): Effect.Effect<ApiFlattenEtape, CaminoError<TitreEtapeToFlattenEtapeErrors>> => { +export type TitreEtapeToFlattenEtapeErrors = typeof pasDHeritageCharge | typeof pasDeSlug | ZodUnparseable +export const iTitreEtapeToFlattenEtape = (machineInfo: MachineInfo, titreEtape: ITitreEtape): Effect.Effect<ApiFlattenEtape, CaminoError<TitreEtapeToFlattenEtapeErrors>> => { return Effect.Do.pipe( - Effect.bind('titreTypeId', () => { - const titreTypeId = titreEtape.demarche?.titre?.typeId - if (isNotNullNorUndefined(titreTypeId)) { - return Effect.succeed(titreTypeId) - } - return Effect.fail({ message: pasDeDemarcheOuDeTitreCharge }) - }), - Effect.bind('demarcheTypeId', () => { - const demarcheTypeId = titreEtape.demarche?.typeId - if (isNullOrUndefined(demarcheTypeId)) { - return Effect.fail({ message: pasDeDemarcheChargee }) - } - return Effect.succeed(demarcheTypeId) - }), Effect.bind('heritageProps', () => { const heritageProps = EtapesTypes[titreEtape.typeId].fondamentale ? titreEtape.heritageProps : defaultHeritageProps if (isNullOrUndefined(heritageProps)) { @@ -67,9 +52,7 @@ export const iTitreEtapeToFlattenEtape = (titreEtape: ITitreEtape): Effect.Effec return Effect.succeed(slug) }), Effect.bind('heritageContenu', () => zodParseEffect(heritageContenuValidator, titreEtape.heritageContenu)), - Effect.bind('contenu', ({ titreTypeId, demarcheTypeId, heritageContenu }) => - Effect.succeed(simpleContenuToFlattenedContenu(titreTypeId, demarcheTypeId, titreEtape.typeId, titreEtape.contenu ?? {}, heritageContenu)) - ), + Effect.bind('contenu', ({ heritageContenu }) => Effect.succeed(simpleContenuToFlattenedContenu(machineInfo, titreEtape.typeId, titreEtape.contenu ?? {}, heritageContenu))), Effect.map(({ heritageProps, slug, contenu }) => { const flattenEtape: FlattenEtape = { ...titreEtape, diff --git a/packages/api/src/api/graphql/resolvers/_titre-etape.ts b/packages/api/src/api/graphql/resolvers/_titre-etape.ts index 11a505b94..aa08885c7 100644 --- a/packages/api/src/api/graphql/resolvers/_titre-etape.ts +++ b/packages/api/src/api/graphql/resolvers/_titre-etape.ts @@ -3,14 +3,13 @@ import { IHeritageContenu, IHeritageElement, IHeritageProps, ITitreDemarche, ITi import { titreEtapeHeritagePropsFind } from '../../../business/utils/titre-etape-heritage-props-find' import { titreEtapeHeritageContenuFind } from '../../../business/utils/titre-etape-heritage-contenu-find' import { titreEtapesSortAscByOrdre, titreEtapesSortDescByOrdre } from '../../../business/utils/titre-etapes-sort' -import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' -import { TitreTypeId } from 'camino-common/src/static/titresTypes' import { getKeys, isNotNullNorUndefined, RecordPartial } from 'camino-common/src/typescript-tools' import { getSections, Section } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/sections' import { ETAPE_HERITAGE_PROPS, isHeritageProps } from 'camino-common/src/heritage' import { EtapeTypeId, EtapesTypes } from 'camino-common/src/static/etapesTypes' import { CaminoDate } from 'camino-common/src/date' import { EtapeId } from 'camino-common/src/etape' +import { MachineInfo } from 'camino-common/src/machines' const titreEtapeHeritagePropsBuild = (date: CaminoDate, titreEtapes: ITitreEtape[] | null, etapeId: EtapeId | null) => { const titreEtapesFiltered = titreEtapesSortAscByOrdre( @@ -59,19 +58,12 @@ const titreEtapeHeritagePropsBuild = (date: CaminoDate, titreEtapes: ITitreEtape return newTitreEtape } -const titreEtapeHeritageContenuBuild = ( - date: CaminoDate, - etapeTypeId: EtapeTypeId, - titreTypeId: TitreTypeId, - demarcheTypeId: DemarcheTypeId, - titreEtapes: ITitreEtape[] | null, - etapeId: EtapeId | null -) => { +const titreEtapeHeritageContenuBuild = (date: CaminoDate, etapeTypeId: EtapeTypeId, machineInfo: MachineInfo, titreEtapes: ITitreEtape[] | null, etapeId: EtapeId | null) => { if (!titreEtapes) { titreEtapes = [] } - const sections = getSections(titreTypeId, demarcheTypeId, etapeTypeId) + const sections = getSections(machineInfo, etapeTypeId) const titreEtape = { id: 'new-titre-etape', date, @@ -83,7 +75,7 @@ const titreEtapeHeritageContenuBuild = ( titreEtapesFiltered.splice(0, 0, titreEtape) const etapeSectionsDictionary = titreEtapesFiltered.reduce<RecordPartial<string, Section[]>>((acc, e) => { - acc[e.id] = getSections(titreTypeId, demarcheTypeId, e.typeId) + acc[e.id] = getSections(machineInfo, e.typeId) return acc }, {}) @@ -127,14 +119,7 @@ const titreEtapeHeritageContenuBuild = ( return { contenu, heritageContenu } } -export const titreEtapeHeritageBuild = ( - date: CaminoDate, - etapeTypeId: EtapeTypeId, - titreDemarche: ITitreDemarche, - titreTypeId: TitreTypeId, - demarcheTypeId: DemarcheTypeId, - etapeId: EtapeId | null -): ITitreEtape => { +export const titreEtapeHeritageBuild = (date: CaminoDate, machineInfo: MachineInfo, etapeTypeId: EtapeTypeId, titreDemarche: ITitreDemarche, etapeId: EtapeId | null): ITitreEtape => { let titreEtape = {} as ITitreEtape const etapeType = EtapesTypes[etapeTypeId] @@ -143,9 +128,9 @@ export const titreEtapeHeritageBuild = ( titreEtape = titreEtapeHeritagePropsBuild(date, titreDemarche.etapes ?? [], etapeId) } - const sections = getSections(titreTypeId, demarcheTypeId, etapeType.id) + const sections = getSections(machineInfo, etapeType.id) if (sections.length) { - const { contenu, heritageContenu } = titreEtapeHeritageContenuBuild(date, etapeTypeId, titreTypeId, demarcheTypeId, titreDemarche.etapes ?? [], etapeId) + const { contenu, heritageContenu } = titreEtapeHeritageContenuBuild(date, etapeTypeId, machineInfo, titreDemarche.etapes ?? [], etapeId) titreEtape.contenu = contenu titreEtape.heritageContenu = heritageContenu diff --git a/packages/api/src/api/graphql/resolvers/titres-etapes.ts b/packages/api/src/api/graphql/resolvers/titres-etapes.ts index 2d43165d7..cb5e06ebe 100644 --- a/packages/api/src/api/graphql/resolvers/titres-etapes.ts +++ b/packages/api/src/api/graphql/resolvers/titres-etapes.ts @@ -11,6 +11,8 @@ import { CaminoDate } from 'camino-common/src/date' import { titreEtapeFormatFields } from '../../_format/_fields' import { EtapeId } from 'camino-common/src/etape' import { DemarcheId } from 'camino-common/src/demarche' +import { MachineInfo } from 'camino-common/src/machines' +import { isNullOrUndefined } from 'camino-common/src/typescript-tools' export const etapeHeritage = async ( { date, titreDemarcheId, typeId, etapeId }: { date: CaminoDate; titreDemarcheId: DemarcheId; typeId: EtapeTypeId; etapeId: EtapeId | null }, @@ -19,7 +21,9 @@ export const etapeHeritage = async ( try { let titreDemarche = await titreDemarcheGet(titreDemarcheId, { fields: {} }, user) - if (!titreDemarche) throw new Error("la démarche n'existe pas") + if (isNullOrUndefined(titreDemarche)) { + throw new Error("la démarche n'existe pas") + } titreDemarche = await titreDemarcheGet( titreDemarcheId, @@ -32,8 +36,17 @@ export const etapeHeritage = async ( userSuper ) - const titreEtape = titreEtapeHeritageBuild(date, typeId, titreDemarche!, titreDemarche!.titre!.typeId, titreDemarche!.typeId, etapeId) - const titreTypeId = titreDemarche?.titre?.typeId + if (isNullOrUndefined(titreDemarche)) { + throw new Error("la démarche n'existe pas") + } + + const machineInfo = MachineInfo.withMachineId(titreDemarche.titre!.typeId, titreDemarche.typeId, titreDemarche.id, titreDemarche.machineId) + if (!machineInfo.valid) { + throw new Error(machineInfo.error) + } + + const titreEtape = titreEtapeHeritageBuild(date, machineInfo.value, typeId, titreDemarche!, etapeId) + const titreTypeId = titreDemarche.titre?.typeId if (!titreTypeId) { throw new Error(`le type du titre de l'étape ${titreEtape.id} n'est pas chargé`) } diff --git a/packages/api/src/api/graphql/titres-demarches.test.integration.ts b/packages/api/src/api/graphql/titres-demarches.test.integration.ts index acc9f34b3..01b18e453 100644 --- a/packages/api/src/api/graphql/titres-demarches.test.integration.ts +++ b/packages/api/src/api/graphql/titres-demarches.test.integration.ts @@ -152,6 +152,7 @@ const demarcheCreate = async () => { id: demarcheId, titreId, typeId: 'oct', + machineId: null, }, ], }) diff --git a/packages/api/src/api/graphql/titres.test.integration.ts b/packages/api/src/api/graphql/titres.test.integration.ts index 28fbe4281..2a242cc56 100644 --- a/packages/api/src/api/graphql/titres.test.integration.ts +++ b/packages/api/src/api/graphql/titres.test.integration.ts @@ -53,12 +53,14 @@ const titreDemarchesPubliques: ITitreInsert = { titreId: newTitreId('titre-id'), typeId: 'oct', publicLecture: true, + machineId: null, }, { id: newDemarcheId('titre-id-demarche-pro'), titreId: newTitreId('titre-id'), typeId: 'pro', publicLecture: false, + machineId: null, }, ], } @@ -76,6 +78,7 @@ const titreEtapesPubliques: ITitreInsert = { typeId: 'oct', statutId: 'acc', publicLecture: true, + machineId: 'AncienLogigrammeOctroiARM', etapes: [ { id: newEtapeId('titre-id-demarche-id-asc'), @@ -268,6 +271,7 @@ describe('titres', () => { typeId: 'oct', statutId: 'acc', publicLecture: true, + machineId: 'AncienLogigrammeOctroiARM', etapes: [ { id: newEtapeId('titre-id-demarche-id-dpu'), diff --git a/packages/api/src/api/rest/__snapshots__/demarches.test.integration.ts.snap b/packages/api/src/api/rest/__snapshots__/demarches.test.integration.ts.snap index 077fa7f18..723e1bd69 100644 --- a/packages/api/src/api/rest/__snapshots__/demarches.test.integration.ts.snap +++ b/packages/api/src/api/rest/__snapshots__/demarches.test.integration.ts.snap @@ -4,7 +4,7 @@ exports[`getResultatEnConcurrence > Avec un seul satellite 1`] = ` { "demarcheId": "demarcheIdPivotResultat", "demarcheTypeId": "oct", - "firstEtapeDate": "2400-01-03", + "machineId": "ProcedureSpecifique", "perimetreSansSatellite": { "geojson4326_perimetre": { "geometry": { diff --git a/packages/api/src/api/rest/__snapshots__/etapes.test.integration.ts.snap b/packages/api/src/api/rest/__snapshots__/etapes.test.integration.ts.snap new file mode 100644 index 000000000..1e4101031 --- /dev/null +++ b/packages/api/src/api/rest/__snapshots__/etapes.test.integration.ts.snap @@ -0,0 +1,463 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`getEtapesTypesEtapesStatusWithMainStep > nouvelle étapes possibles change de machine en fonction de la date 2`] = ` +{ + "abd": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "adc": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "and": { + "etapeStatutIds": [ + "fai", + "acc", + "rej", + ], + "mainStep": false, + }, + "anf": { + "etapeStatutIds": [ + "pro", + "enc", + "ter", + ], + "mainStep": false, + }, + "apd": { + "etapeStatutIds": [ + "fav", + "def", + "fre", + "dre", + ], + "mainStep": false, + }, + "apo": { + "etapeStatutIds": [ + "fai", + "ajo", + "fav", + "def", + "fre", + "dre", + ], + "mainStep": false, + }, + "app": { + "etapeStatutIds": [ + "fav", + "def", + "fre", + "dre", + ], + "mainStep": false, + }, + "asc": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "css": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "des": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "dex": { + "etapeStatutIds": [ + "aci", + "acc", + "rej", + "rei", + ], + "mainStep": false, + }, + "dpu": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "exp": { + "etapeStatutIds": [ + "fav", + "def", + ], + "mainStep": false, + }, + "ipc": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "mca": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "mco": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "mcr": { + "etapeStatutIds": [ + "fav", + "def", + ], + "mainStep": false, + }, + "mec": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "men": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "mfr": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "mif": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "mno": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "mod": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "ncl": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "ppu": { + "etapeStatutIds": [ + "pro", + "enc", + "ter", + ], + "mainStep": false, + }, + "pqr": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "rca": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "rco": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "rif": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "rpu": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "sas": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "scg": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "spo": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "spp": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, +} +`; + +exports[`getEtapesTypesEtapesStatusWithMainStep > nouvelle étapes possibles change de machine quand on déplace une étape déjà existante 1`] = ` +{ + "abd": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "adc": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "and": { + "etapeStatutIds": [ + "fai", + "acc", + "rej", + ], + "mainStep": false, + }, + "anf": { + "etapeStatutIds": [ + "pro", + "enc", + "ter", + ], + "mainStep": false, + }, + "apd": { + "etapeStatutIds": [ + "fav", + "def", + "fre", + "dre", + ], + "mainStep": false, + }, + "apo": { + "etapeStatutIds": [ + "fai", + "ajo", + "fav", + "def", + "fre", + "dre", + ], + "mainStep": false, + }, + "app": { + "etapeStatutIds": [ + "fav", + "def", + "fre", + "dre", + ], + "mainStep": false, + }, + "asc": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "css": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "des": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "dex": { + "etapeStatutIds": [ + "aci", + "acc", + "rej", + "rei", + ], + "mainStep": false, + }, + "dpu": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "exp": { + "etapeStatutIds": [ + "fav", + "def", + ], + "mainStep": false, + }, + "ipc": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "mca": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "mco": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "mcr": { + "etapeStatutIds": [ + "fav", + "def", + ], + "mainStep": false, + }, + "mec": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "men": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "mfr": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "mif": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "mno": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "mod": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "ncl": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "ppu": { + "etapeStatutIds": [ + "pro", + "enc", + "ter", + ], + "mainStep": false, + }, + "pqr": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "rca": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "rco": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "rif": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "rpu": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "sas": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "scg": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "spo": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "spp": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, +} +`; diff --git a/packages/api/src/api/rest/activites.test.integration.ts b/packages/api/src/api/rest/activites.test.integration.ts index cdd8a4c92..94ec45f38 100644 --- a/packages/api/src/api/rest/activites.test.integration.ts +++ b/packages/api/src/api/rest/activites.test.integration.ts @@ -56,6 +56,7 @@ describe('updateActivite', () => { typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: DemarchesStatutsIds.Accepte, publicLecture: true, + machineId: null, etapes: [ { id: newEtapeId('titre-id-demarche-id-dpu'), diff --git a/packages/api/src/api/rest/demarches.queries.ts b/packages/api/src/api/rest/demarches.queries.ts index 9623f992d..346a99fd0 100644 --- a/packages/api/src/api/rest/demarches.queries.ts +++ b/packages/api/src/api/rest/demarches.queries.ts @@ -50,6 +50,7 @@ import { isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, isNullOrUndefined import { demarcheTypeIdValidator } from 'camino-common/src/static/demarchesTypes' import { titreTypeIdValidator } from 'camino-common/src/static/titresTypes' import { titreIdValidator, titreSlugValidator } from 'camino-common/src/validators/titres' +import { machineIdValidator } from 'camino-common/src/validators/machine' const getEtapesByDemarcheIdDbValidator = z.object({ id: etapeIdValidator, @@ -138,6 +139,7 @@ const getDemarcheByIdOrSlugValidator = z.object({ demarche_slug: demarcheSlugValidator, demarche_type_id: demarcheTypeIdValidator, demarche_description: z.string().nullable(), + machine_id: machineIdValidator.nullable(), titre_id: titreIdValidator, titre_slug: titreSlugValidator, titre_type_id: titreTypeIdValidator, @@ -163,6 +165,7 @@ const getDemarcheByIdOrSlugDb = sql<Redefine<IGetDemarcheByIdOrSlugDbQuery, { id select td.id as demarche_id, td.slug as demarche_slug, + td.machine_id, td.type_id as demarche_type_id, td.description as demarche_description, td.entreprises_lecture, @@ -264,6 +267,7 @@ const multipolygontoFeatureMultipolygon = (multipolygon: MultiPolygon): FeatureM const getDemarchePivotEnConcurrenceDbValidator = commonTitreEnConcurrenceValidator .pick({ demarcheId: true, + machineId: true, demarcheTypeId: true, titreNom: true, titreSlug: true, @@ -356,6 +360,7 @@ select t.slug AS "titreSlug", td.type_id AS "demarcheTypeId", td.id as "demarcheId", + td.machine_id as "machineId", t.type_id AS "titreTypeId", ST_AsGeoJSON(ST_Multi(te.geojson4326_perimetre))::json as "perimetreTotalGeojson4326", te.surface as "perimetreTotalSurface", diff --git a/packages/api/src/api/rest/demarches.queries.types.ts b/packages/api/src/api/rest/demarches.queries.types.ts index 9254f5bb4..04f9b9625 100644 --- a/packages/api/src/api/rest/demarches.queries.types.ts +++ b/packages/api/src/api/rest/demarches.queries.types.ts @@ -60,6 +60,7 @@ export interface IGetDemarcheByIdOrSlugDbResult { demarche_slug: string | null; demarche_type_id: string; entreprises_lecture: boolean; + machine_id: string | null; public_lecture: boolean; titre_id: string; titre_nom: string; @@ -118,6 +119,7 @@ export interface IGetDemarchePivotEnConcurrenceDbParams { export interface IGetDemarchePivotEnConcurrenceDbResult { demarcheId: string; demarcheTypeId: string; + machineId: string | null; perimetreTotalGeojson4326: Json | null; perimetreTotalSurface: number | null; titreNom: string; diff --git a/packages/api/src/api/rest/demarches.test.integration.ts b/packages/api/src/api/rest/demarches.test.integration.ts index c339def22..e982f06cd 100644 --- a/packages/api/src/api/rest/demarches.test.integration.ts +++ b/packages/api/src/api/rest/demarches.test.integration.ts @@ -259,8 +259,12 @@ describe('demarcheCreer', () => { { titreId, typeId: DEMARCHES_TYPES_IDS.Octroi, description: '' } ) - expect(res.status).toBe(HTTP_STATUS.INTERNAL_SERVER_ERROR) - expect(res.body.message).toBe('droits insuffisants') + expect(res.body).toMatchInlineSnapshot(` + { + "message": "Droits insuffisants pour créer la démarche", + "status": 400, + } + `) }) test('peut créer une démarche (utilisateur super)', async () => { @@ -284,8 +288,12 @@ describe('demarcheCreer', () => { }, { titreId: newTitreId('unknown'), typeId: DEMARCHES_TYPES_IDS.Octroi, description: '' } ) - expect(res.status).toBe(HTTP_STATUS.INTERNAL_SERVER_ERROR) - expect(res.body.message).toBe("le titre n'existe pas") + expect(res.body).toMatchInlineSnapshot(` + { + "message": "le titre n'existe pas", + "status": 404, + } + `) }) test('peut créer une démarche (utilisateur admin)', async () => { @@ -327,8 +335,12 @@ describe('demarcheCreer', () => { { titreId, typeId: DEMARCHES_TYPES_IDS.Octroi, description: '' } ) - expect(res.status).toBe(HTTP_STATUS.INTERNAL_SERVER_ERROR) - expect(res.body.message).toBe("le titre n'existe pas") + expect(res.body).toMatchInlineSnapshot(` + { + "message": "le titre n'existe pas", + "status": 404, + } + `) }) }) @@ -353,6 +365,7 @@ describe('getDemarchesEnConcurrence', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: 'ProcedureSpecifique', id: demarcheIdPivot, titreId: titreIdPivot, typeId: DEMARCHES_TYPES_IDS.Octroi, @@ -375,6 +388,7 @@ describe('getDemarchesEnConcurrence', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: 'ProcedureSpecifique', id: demarcheIdSatellite1, titreId: titreIdSatellite1, typeId: DEMARCHES_TYPES_IDS.Octroi, @@ -403,6 +417,7 @@ describe('getDemarchesEnConcurrence', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: 'ProcedureSpecifique', id: demarcheIdSatellite2, titreId: titreIdSatellite2, typeId: DEMARCHES_TYPES_IDS.Octroi, @@ -503,6 +518,7 @@ describe('getDemarcheByIdOrSlug', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: 'ProcedureSpecifique', id: demarcheId, titreId: titreId, slug: demarcheSlug, @@ -549,6 +565,7 @@ describe('getDemarcheByIdOrSlug', () => { "demarche_slug": "demarche-slug", "demarche_type_id": "oct", "first_etape_date": "2400-01-03", + "machine_id": "ProcedureSpecifique", "titre_id": "titreIdGetDemarche", "titre_nom": "titre", "titre_slug": "slug-titre", @@ -616,6 +633,7 @@ describe('getResultatEnConcurrence', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: 'ProcedureSpecifique', id: demarcheIdPivot, titreId: titreIdPivot, typeId: DEMARCHES_TYPES_IDS.Octroi, @@ -664,6 +682,7 @@ describe('getResultatEnConcurrence', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: 'ProcedureSpecifique', id: demarcheIdSatellite1, titreId: titreIdSatellite1, typeId: DEMARCHES_TYPES_IDS.Octroi, diff --git a/packages/api/src/api/rest/demarches.ts b/packages/api/src/api/rest/demarches.ts index 1ba20b73e..e33bb5267 100644 --- a/packages/api/src/api/rest/demarches.ts +++ b/packages/api/src/api/rest/demarches.ts @@ -1,7 +1,7 @@ import { Pool } from 'pg' import { HTTP_STATUS } from 'camino-common/src/http' import { CaminoRequest, CustomResponse } from './express-type' -import { DemarcheCreationOutput, demarcheIdOrSlugValidator, GetDemarcheMiseEnConcurrence, GetResultatMiseEnConcurrence } from 'camino-common/src/demarche' +import { DemarcheCreationOutput, demarcheIdOrSlugValidator, DemarcheSlug, GetDemarcheMiseEnConcurrence, GetResultatMiseEnConcurrence } from 'camino-common/src/demarche' import { getDemarcheByIdOrSlug, GetDemarcheByIdOrSlugErrors, @@ -13,19 +13,22 @@ import { } from './demarches.queries' import { GetDemarcheByIdOrSlug } from 'camino-common/src/titres' import { getAdministrationsLocalesByTitreId, getDemarchesByTitreId, getTitreByIdOrSlug, GetTitreByIdOrSlugErrors, getTitulairesAmodiatairesByTitreId } from './titres.queries' -import { isNullOrUndefined, memoize } from 'camino-common/src/typescript-tools' +import { isNotNullNorUndefined, isNullOrUndefined, memoize } from 'camino-common/src/typescript-tools' import { canReadDemarche } from './permissions/demarches' -import { titreDemarcheArchive, titreDemarcheCreate, titreDemarcheGet } from '../../database/queries/titres-demarches' +import { titreDemarcheArchive, titreDemarcheGet } from '../../database/queries/titres-demarches' import { titreDemarcheUpdateTask } from '../../business/titre-demarche-update' import { canCreateDemarche, canCreateTravaux, canDeleteDemarche, canPublishResultatMiseEnConcurrence } from 'camino-common/src/permissions/titres-demarches' import { userSuper } from '../../database/user-super' import { RestNewGetCall, RestNewPostCall } from '../../server/rest' import { Effect, Match } from 'effect' -import { isDemarcheTypeId, isTravaux } from 'camino-common/src/static/demarchesTypes' +import { isTravaux } from 'camino-common/src/static/demarchesTypes' import { titreGet } from '../../database/queries/titres' -import { CaminoApiError } from '../../types' +import { CaminoApiError, ITitreDemarche } from '../../types' import { EffectDbQueryAndValidateErrors } from '../../pg-database' -import { callAndExit, filterOrFailFromValidWithError } from '../../tools/fp-tools' +import { filterOrFailFromValidWithError } from '../../tools/fp-tools' +import { DBTitre } from '../../database/models/titres' +import { MachineInfo } from 'camino-common/src/machines' +import { createDemarche, CreateDemarcheErrors } from './titre-demande.queries' const canReadDemarcheError = 'impossible de savoir si on peut lire la démarche' as const @@ -119,52 +122,83 @@ export const demarcheSupprimer = } } -export const demarcheCreer: RestNewPostCall<'/rest/demarches'> = (rootPipe): Effect.Effect<DemarcheCreationOutput, CaminoApiError<string>> => { - return rootPipe.pipe( - Effect.flatMap(({ user, body: demarche, pool }) => - Effect.tryPromise({ - try: async () => { - const titre = await titreGet(demarche.titreId, { fields: { pointsEtape: { id: {} } } }, user) - - if (!titre) throw new Error("le titre n'existe pas") - - if (!isDemarcheTypeId(demarche.typeId)) { - throw new Error('droits insuffisants') - } - if (titre.administrationsLocales === undefined) { - throw new Error('les administrations locales doivent être chargées') - } - - const demarches = await callAndExit(getDemarchesByTitreId(pool, demarche.titreId)) - - if (isTravaux(demarche.typeId) && !canCreateTravaux(user, titre.typeId, titre.administrationsLocales ?? [], demarches)) { - throw new Error('droits insuffisants') - } - if (!isTravaux(demarche.typeId) && !canCreateDemarche(user, titre.typeId, titre.titreStatutId, titre.administrationsLocales ?? [], demarches)) { - throw new Error('droits insuffisants') - } - - const demarcheCreated = await titreDemarcheCreate(demarche) - - await titreDemarcheUpdateTask(pool, demarcheCreated.id, demarcheCreated.titreId) - - const demarcheUpdate = await titreDemarcheGet(demarcheCreated.id, { fields: { id: {} } }, user) - - if (isNullOrUndefined(demarcheUpdate?.slug)) { - throw new Error("Problème lors de l'enregistrement de la démarche") - } +const impossibleDeRecupererLeTitre = 'impossible de récupérer le titre' as const +const titreInexistant = "le titre n'existe pas" as const - return { slug: demarcheUpdate.slug } - }, - catch: unknown => { - // TODO 2024-08-08 il faut utiliser effect au dessus pour pouvoir mettre le bon code http - if (unknown instanceof Error) { - return { message: unknown.message, status: HTTP_STATUS.INTERNAL_SERVER_ERROR } - } +const administrationsNonChargees = 'Les administrations ne sont pas chargées' as const +const droitsInsuffisantsPourCreerLaDemarche = 'Droits insuffisants pour créer la démarche' as const +const impossibleDeCreerLaDemarche = 'Impossible de créer la démarche' as const +const erreurLorsDeLaMiseAJourDesTaches = 'Une erreur est survenue lors de la mise à jour des taches de la démarche' as const +const impossibleDeRecupererLaDemarcheCree = 'Impossible de récupérer la démarche crée' as const +type DemarcheCreerErrors = + | typeof impossibleDeRecupererLeTitre + | typeof titreInexistant + | typeof administrationsNonChargees + | typeof droitsInsuffisantsPourCreerLaDemarche + | typeof impossibleDeCreerLaDemarche + | typeof erreurLorsDeLaMiseAJourDesTaches + | typeof impossibleDeRecupererLaDemarcheCree + | EffectDbQueryAndValidateErrors + | CreateDemarcheErrors - return { message: "Problème lors de l'enregistrement de la démarche" as const, extra: unknown, status: HTTP_STATUS.INTERNAL_SERVER_ERROR } - }, +export const demarcheCreer: RestNewPostCall<'/rest/demarches'> = (rootPipe): Effect.Effect<DemarcheCreationOutput, CaminoApiError<DemarcheCreerErrors>> => { + return rootPipe.pipe( + Effect.bind('titre', ({ user, body: demarche }) => + Effect.tryPromise({ + try: () => titreGet(demarche.titreId, { fields: { pointsEtape: { id: {} } } }, user), + catch: error => ({ message: impossibleDeRecupererLeTitre, extra: error }), + }).pipe( + Effect.filterOrFail( + (titre): titre is NonNullable<DBTitre> => isNotNullNorUndefined(titre), + () => ({ message: titreInexistant }) + ), + Effect.filterOrFail( + titre => isNotNullNorUndefined(titre.administrationsLocales), + () => ({ message: administrationsNonChargees }) + ) + ) + ), + Effect.bind('demarches', ({ pool, body: demarche }) => getDemarchesByTitreId(pool, demarche.titreId)), + Effect.filterOrFail( + ({ body: demarche, user, titre, demarches }) => + (isTravaux(demarche.typeId) && canCreateTravaux(user, titre.typeId, titre.administrationsLocales ?? [], demarches)) || + (!isTravaux(demarche.typeId) && canCreateDemarche(user, titre.typeId, titre.titreStatutId, titre.administrationsLocales ?? [], demarches)), + () => ({ message: droitsInsuffisantsPourCreerLaDemarche }) + ), + Effect.bind('demarcheId', ({ body, pool, titre }) => createDemarche(pool, titre.id, titre.typeId, body.typeId, body.description)), + Effect.tap(({ pool, demarcheId, titre }) => + Effect.tryPromise({ + try: () => titreDemarcheUpdateTask(pool, demarcheId, titre.id), + catch: error => ({ message: erreurLorsDeLaMiseAJourDesTaches, extra: error }), }) + ), + Effect.bind('demarcheUpdate', ({ demarcheId, user }) => + Effect.tryPromise({ + try: () => titreDemarcheGet(demarcheId, { fields: { id: {} } }, user), + catch: error => ({ message: impossibleDeRecupererLaDemarcheCree, extra: error }), + }).pipe( + Effect.filterOrFail( + (demarcheUpdate): demarcheUpdate is NonNullable<ITitreDemarche & { slug: DemarcheSlug }> => isNotNullNorUndefined(demarcheUpdate?.slug), + () => ({ message: impossibleDeRecupererLaDemarcheCree }) + ) + ) + ), + Effect.map(({ demarcheUpdate }) => ({ slug: demarcheUpdate.slug })), + Effect.mapError(caminoError => + Match.value(caminoError.message).pipe( + Match.whenOr( + 'impossible de récupérer le titre', + "Impossible d'exécuter la requête dans la base de données", + 'Impossible de récupérer la démarche crée', + 'Les administrations ne sont pas chargées', + 'Les données en base ne correspondent pas à ce qui est attendu', + 'Une erreur est survenue lors de la mise à jour des taches de la démarche', + () => ({ ...caminoError, status: HTTP_STATUS.INTERNAL_SERVER_ERROR }) + ), + Match.whenOr('Droits insuffisants pour créer la démarche', () => ({ ...caminoError, status: HTTP_STATUS.BAD_REQUEST })), + Match.whenOr("le titre n'existe pas", () => ({ ...caminoError, status: HTTP_STATUS.NOT_FOUND })), + Match.exhaustive + ) ) ) } @@ -186,20 +220,34 @@ export const getDemarchesEnConcurrence: RestNewGetCall<'/rest/demarches/:demarch ) } +const incoherentMachineInfo = 'Machine associée à la démarche incohérente' as const +const insufficientPermission = 'droits insuffisants' as const +type GetResultatEnConcurrenceErrors = + | EffectDbQueryAndValidateErrors + | GetDemarcheByIdOrSlugErrors + | typeof insufficientPermission + | typeof incoherentMachineInfo + | GetFirstEtapeDateByDemarcheIdOrSlugErrors export const getResultatEnConcurrence: RestNewGetCall<'/rest/demarches/:demarcheId/resultatMiseEnConcurrence'> = ( rootPipe -): Effect.Effect<GetResultatMiseEnConcurrence, CaminoApiError<EffectDbQueryAndValidateErrors | GetDemarcheByIdOrSlugErrors | 'droits insuffisants' | GetFirstEtapeDateByDemarcheIdOrSlugErrors>> => { +): Effect.Effect<GetResultatMiseEnConcurrence, CaminoApiError<GetResultatEnConcurrenceErrors>> => { return rootPipe.pipe( Effect.bind('etapes', ({ pool, params }) => getEtapesByDemarcheId(pool, params.demarcheId)), Effect.bind('demarche', ({ pool, params }) => getDemarcheByIdOrSlug(pool, params.demarcheId)), - Effect.tap(({ etapes, demarche, user }) => - filterOrFailFromValidWithError(canPublishResultatMiseEnConcurrence(user, demarche.titre_type_id, demarche.demarche_type_id, etapes, demarche.demarche_id), 'droits insuffisants' as const) - ), + Effect.bind('machineInfo', ({ demarche }) => { + const machineInfo = MachineInfo.withMachineId(demarche.titre_type_id, demarche.demarche_type_id, demarche.demarche_id, demarche.machine_id) + if (machineInfo.valid) { + return Effect.succeed(machineInfo.value) + } + + return Effect.fail({ message: incoherentMachineInfo, extra: machineInfo.error }) + }), + Effect.tap(({ etapes, machineInfo, user }) => filterOrFailFromValidWithError(canPublishResultatMiseEnConcurrence(user, machineInfo, etapes), 'droits insuffisants' as const)), Effect.flatMap(({ pool, params, user }) => getDemarchePivotEnConcurrence(pool, params.demarcheId, user)), Effect.mapError(caminoError => Match.value(caminoError.message).pipe( Match.whenOr("La démarche n'existe pas", 'Impossible de trouver la date de la première étape', () => ({ ...caminoError, status: HTTP_STATUS.BAD_REQUEST })), - Match.whenOr("Impossible d'exécuter la requête dans la base de données", 'Les données en base ne correspondent pas à ce qui est attendu', () => ({ + Match.whenOr("Impossible d'exécuter la requête dans la base de données", 'Machine associée à la démarche incohérente', 'Les données en base ne correspondent pas à ce qui est attendu', () => ({ ...caminoError, status: HTTP_STATUS.INTERNAL_SERVER_ERROR, })), diff --git a/packages/api/src/api/rest/entreprises.test.integration.ts b/packages/api/src/api/rest/entreprises.test.integration.ts index 86b13b415..1bdff3998 100644 --- a/packages/api/src/api/rest/entreprises.test.integration.ts +++ b/packages/api/src/api/rest/entreprises.test.integration.ts @@ -10,7 +10,6 @@ import { tempDocumentNameValidator } from 'camino-common/src/document' import { entreprisesEtablissementsFetch, entreprisesFetch, tokenInitialize } from '../../tools/api-insee/fetch' import { entreprise, entrepriseAndEtablissements } from '../../../tests/__mocks__/fetch-insee-api' import type { Pool } from 'pg' -import { titreDemarcheCreate } from '../../database/queries/titres-demarches' import { titreEtapeCreate } from '../../database/queries/titres-etapes' import { toCaminoAnnee, toCaminoDate } from 'camino-common/src/date' import { HTTP_STATUS } from 'camino-common/src/http' @@ -24,6 +23,9 @@ import { etapeCreate } from './rest-test-utils' import { insertTitreGraph } from '../../../tests/integration-test-helper' import { callAndExit } from '../../tools/fp-tools' import { z } from 'zod' +import { createDemarche } from './titre-demande.queries' +import { TITRES_TYPES_IDS } from 'camino-common/src/static/titresTypes' +import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes' console.info = vi.fn() console.warn = vi.fn() console.error = vi.fn() @@ -316,24 +318,23 @@ describe('getEntrepriseDocument', () => { await entrepriseUpsert({ id: entrepriseId, nom: entrepriseId }) const titreId = newTitreId() + const titreTypeId = TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX await insertTitreGraph({ id: titreId, nom: '', - typeId: 'arm', + typeId: titreTypeId, titreStatutId: 'ind', slug: titreSlugValidator.parse('arm-slug'), propsTitreEtapesIds: {}, }) - const titreDemarche = await titreDemarcheCreate({ - titreId, - typeId: 'oct', - }) + const titreDemarcheId = await callAndExit(createDemarche(dbPool, titreId, titreTypeId, DEMARCHES_TYPES_IDS.Octroi)) + const titreEtape = await titreEtapeCreate( { typeId: 'mfr', statutId: 'fai', - titreDemarcheId: titreDemarche.id, + titreDemarcheId: titreDemarcheId, date: toCaminoDate('2022-01-01'), ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, diff --git a/packages/api/src/api/rest/etape-creer.test.integration.ts b/packages/api/src/api/rest/etape-creer.test.integration.ts index 0fbb6a097..5d3236154 100644 --- a/packages/api/src/api/rest/etape-creer.test.integration.ts +++ b/packages/api/src/api/rest/etape-creer.test.integration.ts @@ -53,6 +53,7 @@ const demarcheCreate = async (titreTypeId: TitreTypeId = 'arm') => { propsTitreEtapesIds: {}, demarches: [ { + machineId: null, id: titreDemarcheId, titreId: titreId, typeId: 'oct', @@ -125,6 +126,7 @@ describe('etapeCreer', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: 'ProcedureSpecifique', id: demarcheId, titreId: titreId, typeId: DEMARCHES_TYPES_IDS.Octroi, diff --git a/packages/api/src/api/rest/etape-deposer.test.integration.ts b/packages/api/src/api/rest/etape-deposer.test.integration.ts index 55034704a..696d8bba6 100644 --- a/packages/api/src/api/rest/etape-deposer.test.integration.ts +++ b/packages/api/src/api/rest/etape-deposer.test.integration.ts @@ -133,6 +133,7 @@ describe('etapeDeposer', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: 'ProcedureSimplifiee', id: demarcheId, titreId: titreId, typeId: DEMARCHES_TYPES_IDS.Octroi, diff --git a/packages/api/src/api/rest/etape-modifier.test.integration.ts b/packages/api/src/api/rest/etape-modifier.test.integration.ts index fa59f8348..9318f0345 100644 --- a/packages/api/src/api/rest/etape-modifier.test.integration.ts +++ b/packages/api/src/api/rest/etape-modifier.test.integration.ts @@ -95,6 +95,7 @@ describe('etapeModifier', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: null, id: demarcheId, titreId: newTitreId('titre-id'), typeId: 'oct', @@ -380,6 +381,7 @@ describe('etapeModifier', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: null, id: demarcheId, titreId: titreId, typeId: 'oct', diff --git a/packages/api/src/api/rest/etapes.test.integration.ts b/packages/api/src/api/rest/etapes.test.integration.ts index 2ada5d99e..38c190f8b 100644 --- a/packages/api/src/api/rest/etapes.test.integration.ts +++ b/packages/api/src/api/rest/etapes.test.integration.ts @@ -1,7 +1,7 @@ import { dbManager } from '../../../tests/db-manager' import { userSuper } from '../../database/user-super' import { restCall, restNewCall, restNewDeleteCall, restNewPostCall } from '../../../tests/_utils/index' -import { caminoDateValidator, dateAddDays, toCaminoDate } from 'camino-common/src/date' +import { caminoDateValidator, dateAddDays, firstEtapeDateValidator, toCaminoDate } from 'camino-common/src/date' import { afterAll, beforeAll, test, expect, describe, vi } from 'vitest' import type { Pool } from 'pg' import { HTTP_STATUS } from 'camino-common/src/http' @@ -19,11 +19,13 @@ import { tempDocumentNameValidator } from 'camino-common/src/document' import { idGenerate, newDemarcheId, newEtapeId, newTitreId } from '../../database/models/_format/id-create' import { insertTitreGraph } from '../../../tests/integration-test-helper' import { callAndExit } from '../../tools/fp-tools' -import { DATE_DEBUT_PROCEDURE_SPECIFIQUE_AXM_ARM } from 'camino-common/src/machines' +import { DATE_DEBUT_PRM_OCT, DATE_DEBUT_PROCEDURE_SPECIFIQUE_AXM_ARM, MachineInfo } from 'camino-common/src/machines' import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' import { ETAPES_STATUTS } from 'camino-common/src/static/etapesStatuts' import { copyFileSync, mkdirSync } from 'node:fs' import { z } from 'zod' +import { TITRES_TYPES_IDS } from 'camino-common/src/static/titresTypes' +import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes' console.info = vi.fn() console.error = vi.fn() @@ -46,6 +48,7 @@ describe('getEtapeEntrepriseDocuments', () => { const titreId = newTitreId() const demarcheId = newDemarcheId() const etapeId = newEtapeId() + const dateDemande = toCaminoDate('2025-01-31') await insertTitreGraph({ id: titreId, nom: 'nomTitre', @@ -54,6 +57,7 @@ describe('getEtapeEntrepriseDocuments', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDateValidator.parse(dateDemande)).machineId ?? null, id: demarcheId, titreId, typeId: 'oct', @@ -61,7 +65,7 @@ describe('getEtapeEntrepriseDocuments', () => { { id: etapeId, typeId: ETAPES_TYPES.demande, - date: toCaminoDate('2025-01-31'), + date: dateDemande, isBrouillon: ETAPE_IS_NOT_BROUILLON, statutId: ETAPES_STATUTS.FAIT, titreDemarcheId: demarcheId, @@ -121,6 +125,7 @@ describe('getEtapesTypesEtapesStatusWithMainStep', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: 'AncienLogigrammeOctroiARM', id: demarcheId, titreId, typeId: 'oct', @@ -173,6 +178,7 @@ describe('getEtapesTypesEtapesStatusWithMainStep', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: 'ProcedureSpecifique', id: demarcheId, titreId, typeId: 'oct', @@ -194,10 +200,98 @@ describe('getEtapesTypesEtapesStatusWithMainStep', () => { } `) }) + + test('nouvelle étapes possibles change de machine en fonction de la date', async () => { + const titreId = newTitreId() + const demarcheId = newDemarcheId() + await insertTitreGraph({ + id: titreId, + nom: 'nomTitre', + typeId: TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, + titreStatutId: 'val', + propsTitreEtapesIds: {}, + demarches: [ + { + machineId: null, + id: demarcheId, + titreId, + typeId: DEMARCHES_TYPES_IDS.Octroi, + }, + ], + }) + + const tested = await restNewCall(dbPool, '/rest/etapesTypes/:demarcheId/:date', { demarcheId: demarcheId, date: dateAddDays(DATE_DEBUT_PRM_OCT, 20) }, userSuper) + + expect(tested.body).toMatchInlineSnapshot(` + { + "mfr": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": true, + }, + } + `) + + const testedTde = await restNewCall(dbPool, '/rest/etapesTypes/:demarcheId/:date', { demarcheId: demarcheId, date: dateAddDays(DATE_DEBUT_PRM_OCT, -20) }, userSuper) + expect(testedTde.body).toMatchSnapshot() + expect(tested.body).not.toStrictEqual(testedTde.body) + }) + + test('nouvelle étapes possibles change de machine quand on déplace une étape déjà existante', async () => { + const titreId = newTitreId() + const demarcheId = newDemarcheId() + const etapeId = newEtapeId() + const dateDemande = dateAddDays(DATE_DEBUT_PRM_OCT, -20) + await insertTitreGraph({ + id: titreId, + nom: 'nomTitre', + typeId: TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, + titreStatutId: 'val', + propsTitreEtapesIds: {}, + demarches: [ + { + machineId: null, + id: demarcheId, + titreId, + typeId: DEMARCHES_TYPES_IDS.Octroi, + etapes: [ + { + id: etapeId, + typeId: ETAPES_TYPES.demande, + date: dateDemande, + statutId: ETAPES_STATUTS.FAIT, + isBrouillon: ETAPE_IS_NOT_BROUILLON, + titreDemarcheId: demarcheId, + }, + ], + }, + ], + }) + + const testedTde = await restNewCall(dbPool, '/rest/etapesTypes/:demarcheId/:date', { demarcheId: demarcheId, date: dateDemande }, userSuper, { etapeId }) + expect(testedTde.body).toMatchSnapshot() + + const tested = await restNewCall(dbPool, '/rest/etapesTypes/:demarcheId/:date', { demarcheId, date: dateAddDays(dateDemande, 50) }, userSuper, { etapeId }) + + expect(tested.body).toMatchInlineSnapshot(` + { + "mfr": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": true, + }, + } + `) + expect(tested.body).not.toStrictEqual(testedTde.body) + }) + test('nouvelle étapes possibles prends en compte les brouillons', async () => { const titreId = newTitreId() const demarcheId = newDemarcheId() const etapeId = newEtapeId() + const dateDemande = toCaminoDate('2024-06-27') await insertTitreGraph({ id: titreId, nom: 'nomTitre', @@ -206,6 +300,7 @@ describe('getEtapesTypesEtapesStatusWithMainStep', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDateValidator.parse(dateDemande)).machineId ?? null, id: demarcheId, titreId, typeId: 'oct', @@ -213,7 +308,7 @@ describe('getEtapesTypesEtapesStatusWithMainStep', () => { { id: etapeId, typeId: 'mfr', - date: toCaminoDate('2024-06-27'), + date: dateDemande, titreDemarcheId: demarcheId, statutId: 'fai', isBrouillon: ETAPE_IS_BROUILLON, @@ -258,6 +353,7 @@ describe('etapeSupprimer', () => { const titreId = newTitreId() const demarcheId = newDemarcheId() const etapeId = newEtapeId() + const dateDemande = toCaminoDate('2018-01-01') await insertTitreGraph({ id: titreId, nom: 'nomTitre', @@ -266,6 +362,7 @@ describe('etapeSupprimer', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDateValidator.parse(dateDemande)).machineId ?? null, id: demarcheId, titreId, typeId: 'oct', @@ -277,7 +374,7 @@ describe('etapeSupprimer', () => { isBrouillon: ETAPE_IS_BROUILLON, ordre: 1, titreDemarcheId: demarcheId, - date: toCaminoDate('2018-01-01'), + date: dateDemande, }, ], }, @@ -298,6 +395,7 @@ describe('etapeSupprimer', () => { const titreId = newTitreId() const demarcheId = newDemarcheId() const etapeId = newEtapeId() + const dateDemande = toCaminoDate('2018-01-01') await insertTitreGraph({ id: titreId, nom: 'nomTitre', @@ -306,6 +404,7 @@ describe('etapeSupprimer', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDateValidator.parse(dateDemande)).machineId ?? null, id: demarcheId, titreId, typeId: 'oct', @@ -317,7 +416,7 @@ describe('etapeSupprimer', () => { isBrouillon: ETAPE_IS_BROUILLON, ordre: 1, titreDemarcheId: demarcheId, - date: toCaminoDate('2018-01-01'), + date: dateDemande, }, ], }, @@ -338,6 +437,7 @@ describe('etapeSupprimer', () => { const titreId = newTitreId() const demarcheId = newDemarcheId() const etapeId = newEtapeId() + const dateDemande = toCaminoDate('2018-01-01') await insertTitreGraph({ id: titreId, nom: 'nomTitre', @@ -347,6 +447,7 @@ describe('etapeSupprimer', () => { publicLecture: false, demarches: [ { + machineId: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDateValidator.parse(dateDemande)).machineId ?? null, id: demarcheId, titreId, typeId: 'oct', @@ -360,7 +461,7 @@ describe('etapeSupprimer', () => { isBrouillon: ETAPE_IS_BROUILLON, ordre: 1, titreDemarcheId: demarcheId, - date: toCaminoDate('2018-01-01'), + date: dateDemande, titulaireIds: [titulaireId1], }, ], @@ -391,6 +492,7 @@ describe('getEtapeAvis', () => { const titreId = newTitreId() const demarcheId = newDemarcheId() const etapeId = newEtapeId() + const dateDemande = toCaminoDate('2018-01-01') await insertTitreGraph({ id: titreId, nom: 'nomTitre', @@ -399,6 +501,7 @@ describe('getEtapeAvis', () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDateValidator.parse(dateDemande)).machineId ?? null, id: demarcheId, titreId, typeId: 'oct', @@ -410,7 +513,7 @@ describe('getEtapeAvis', () => { isBrouillon: ETAPE_IS_BROUILLON, ordre: 1, titreDemarcheId: demarcheId, - date: toCaminoDate('2018-01-01'), + date: dateDemande, }, ], }, diff --git a/packages/api/src/api/rest/etapes.ts b/packages/api/src/api/rest/etapes.ts index 56b44029e..0743d590d 100644 --- a/packages/api/src/api/rest/etapes.ts +++ b/packages/api/src/api/rest/etapes.ts @@ -10,7 +10,7 @@ import { ETAPE_IS_BROUILLON, getStatutId, } from 'camino-common/src/etape' -import { demarcheEnregistrementDemandeDateFind, DemarcheId } from 'camino-common/src/demarche' +import { DemarcheId } from 'camino-common/src/demarche' import { HTTP_STATUS } from 'camino-common/src/http' import { CaminoDate, firstEtapeDateValidator, getCurrent } from 'camino-common/src/date' import { titreDemarcheGet } from '../../database/queries/titres-demarches' @@ -20,7 +20,7 @@ import { User, isBureauDEtudes, isEntreprise } from 'camino-common/src/roles' import { canCreateEtape, canDeposeEtape, canDeleteEtape, canEditEtape } from 'camino-common/src/permissions/titres-etapes' import { canBeBrouillon, ETAPES_TYPES, isEtapeTypeId } from 'camino-common/src/static/etapesTypes' -import { NotNullableKeys, getKeys, isNonEmptyArray, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, isNullOrUndefined, memoize, onlyUnique } from 'camino-common/src/typescript-tools' +import { getKeys, isNonEmptyArray, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, isNullOrUndefined, isNullOrUndefinedOrEmpty, memoize, onlyUnique } from 'camino-common/src/typescript-tools' import { Pool } from 'pg' import { EntrepriseDocument, EntrepriseDocumentId, EtapeEntrepriseDocument } from 'camino-common/src/entreprise' import { @@ -66,8 +66,9 @@ import { RestNewDeleteCall, RestNewGetCall, RestNewPostCall, RestNewPutCall } fr import { Effect, Match, Option } from 'effect' import { EffectDbQueryAndValidateErrors } from '../../pg-database' import { CaminoError } from 'camino-common/src/zod-tools' -import { machineFind } from '../../business/rules-demarches/machines' import { TitreEtapeForMachine } from '../../business/rules-demarches/machine-common' +import { MachineInfo } from 'camino-common/src/machines' +import { ApiMachineInfo, demarcheEnregistrementDemandeDateFind } from '../../business/rules-demarches/machines' import { newEtapeId } from '../../database/models/_format/id-create' type GetEtapeEntrepriseDocumentsErrors = EffectDbQueryAndValidateErrors @@ -199,6 +200,7 @@ type DeleteEtapeErrors = | typeof demarcheIntrouvableError | typeof titreIntrouvableError | typeof demarcheInvalideError + | typeof incoherentMachineInfo export const deleteEtape: RestNewDeleteCall<'/rest/etapes/:etapeIdOrSlug'> = (rootPipe): Effect.Effect<Option.Option<never>, CaminoApiError<DeleteEtapeErrors>> => rootPipe.pipe( Effect.bind('etape', ({ params, user }) => @@ -283,8 +285,16 @@ export const deleteEtape: RestNewDeleteCall<'/rest/etapes/:etapeIdOrSlug'> = (ro ) ) ), - Effect.tap(({ fullDemarche, fullTitre, etape }) => { - const { valid, errors: rulesErrors } = titreDemarcheUpdatedEtatValidate(fullDemarche.typeId, fullTitre, etape, fullDemarche.id, fullDemarche.etapes!, true) + Effect.bind('machineInfo', ({ fullDemarche, titre }) => { + const machineInfo = MachineInfo.withMachineId(titre.typeId, fullDemarche.typeId, fullDemarche.id, fullDemarche.machineId) + if (!machineInfo.valid) { + return Effect.fail({ message: incoherentMachineInfo, extra: machineInfo.error }) + } + + return Effect.succeed(machineInfo.value) + }), + Effect.tap(({ fullDemarche, fullTitre, etape, machineInfo }) => { + const { valid, errors: rulesErrors } = titreDemarcheUpdatedEtatValidate(machineInfo, fullTitre.demarches!, etape, fullDemarche.etapes!, true) if (!valid) { return Effect.fail({ message: demarcheInvalideError, detail: rulesErrors.join(', ') }) } @@ -326,6 +336,7 @@ export const deleteEtape: RestNewDeleteCall<'/rest/etapes/:etapeIdOrSlug'> = (ro "Les tâches après mise à jour de l'étape ont échoué", "Une erreur s'est produite lors de la récupération de l'étape", "Une erreur s'est produite lors de la récupération de la démarche", + 'La machine associée à la démarche est incohérente', () => ({ ...caminoError, status: HTTP_STATUS.INTERNAL_SERVER_ERROR, @@ -336,7 +347,14 @@ export const deleteEtape: RestNewDeleteCall<'/rest/etapes/:etapeIdOrSlug'> = (ro ) ) -type GetEtapeErrors = EffectDbQueryAndValidateErrors | TitreEtapeToFlattenEtapeErrors | typeof etapeFetchError | typeof etapeIntrouvableError | typeof etapeIncompletError | typeof droitsManquantsError +type GetEtapeErrors = + | EffectDbQueryAndValidateErrors + | TitreEtapeToFlattenEtapeErrors + | typeof etapeFetchError + | typeof etapeIntrouvableError + | typeof etapeIncompletError + | typeof droitsManquantsError + | typeof incoherentMachineInfo export const getEtape: RestNewGetCall<'/rest/etapes/:etapeIdOrSlug'> = (rootPipe): Effect.Effect<FlattenEtape, CaminoApiError<GetEtapeErrors>> => rootPipe.pipe( Effect.bind('etape', ({ user, params }) => @@ -382,7 +400,15 @@ export const getEtape: RestNewGetCall<'/rest/etapes/:etapeIdOrSlug'> = (rootPipe }), () => ({ message: droitsManquantsError }) ), - Effect.flatMap(({ etape }) => iTitreEtapeToFlattenEtape(etape)), + Effect.bind('machineInfo', ({ demarche, titre }) => { + const machineInfo = MachineInfo.withMachineId(titre.typeId, demarche.typeId, demarche.id, demarche.machineId) + if (!machineInfo.valid) { + return Effect.fail({ message: incoherentMachineInfo, extra: machineInfo.error }) + } + + return Effect.succeed(machineInfo.value) + }), + Effect.flatMap(({ etape, machineInfo }) => iTitreEtapeToFlattenEtape(machineInfo, etape)), Effect.mapError(caminoError => Match.value(caminoError.message).pipe( Match.when("L'étape n'existe pas", () => ({ @@ -398,9 +424,8 @@ export const getEtape: RestNewGetCall<'/rest/etapes/:etapeIdOrSlug'> = (rootPipe 'Problème de validation de données', "Une erreur s'est produite lors de la récupération de l'étape", "pas d'héritage chargé", - 'pas de démarche chargée', - 'pas de démarche ou de titre chargé', 'pas de slug', + 'La machine associée à la démarche est incohérente', () => ({ ...caminoError, status: HTTP_STATUS.INTERNAL_SERVER_ERROR, @@ -449,14 +474,14 @@ export const arePointsOnPerimeter = (perimetre: FeatureMultiPolygon, points: Fea }) } const getForagesProperties = ( - titreTypeId: TitreTypeId, + machineInfo: MachineInfo, geojsonOrigineGeoSystemeId: GraphqlEtape['geojsonOrigineGeoSystemeId'], geojsonOrigineForages: GraphqlEtape['geojsonOrigineForages'], pool: Pool ): Effect.Effect<Pick<GraphqlEtape, 'geojson4326Forages' | 'geojsonOrigineForages'>, CaminoError<ConvertPointsErrors>> => Effect.Do.pipe( Effect.flatMap(() => { - if (canHaveForages(titreTypeId) && isNotNullNorUndefined(geojsonOrigineForages) && isNotNullNorUndefined(geojsonOrigineGeoSystemeId)) { + if (canHaveForages(machineInfo) && isNotNullNorUndefined(geojsonOrigineForages) && isNotNullNorUndefined(geojsonOrigineGeoSystemeId)) { return convertPoints(pool, geojsonOrigineGeoSystemeId, geojsonOrigineForages) } return Effect.succeed(null) @@ -477,7 +502,7 @@ const getPerimetreInfosInternal = ( geojson4326Perimetre: GraphqlEtape['geojson4326Perimetre'], geojsonOriginePerimetre: GraphqlEtape['geojsonOriginePerimetre'], geojsonOriginePoints: GraphqlEtape['geojsonOriginePoints'], - titreTypeId: TitreTypeId, + machineInfo: MachineInfo, geojsonOrigineGeoSystemeId: GraphqlEtape['geojsonOrigineGeoSystemeId'], geojsonOrigineForages: GraphqlEtape['geojsonOrigineForages'] ): Effect.Effect<PerimetreInfos, CaminoError<PerimetreInfosError>> => { @@ -492,7 +517,7 @@ const getPerimetreInfosInternal = ( () => ({ message: lespointsdoiventetresurleperimetreerror }) ), Effect.bind('geojsonInformation', value => getGeojsonInformation(pool, value.geometry)), - Effect.bind('forage', () => getForagesProperties(titreTypeId, geojsonOrigineGeoSystemeId, geojsonOrigineForages, pool)), + Effect.bind('forage', () => getForagesProperties(machineInfo, geojsonOrigineGeoSystemeId, geojsonOrigineForages, pool)), Effect.let('secteursMaritime', ({ geojsonInformation: { secteurs } }) => secteurs.map(s => getSecteurMaritime(s))), Effect.map(({ secteursMaritime, geojsonInformation: { departements, surface, communes, forets, sdom }, forage: { geojson4326Forages } }) => ({ surface, @@ -518,7 +543,8 @@ const getPerimetreInfosInternal = ( ) ) } -type GetFlattenEtapeErrors = PerimetreInfosError | TitreEtapeToFlattenEtapeErrors +const incoherentMachineInfo = 'La machine associée à la démarche est incohérente' as const +type GetFlattenEtapeErrors = PerimetreInfosError | TitreEtapeToFlattenEtapeErrors | typeof incoherentMachineInfo const getFlattenEtape = ( etape: RestEtapeCreation | RestEtapeModification, demarche: ITitreDemarche, @@ -530,13 +556,22 @@ const getFlattenEtape = ( etapeOldDemarcheIdsConsentement: TitreEtapeForMachine['demarcheIdsConsentement'], pool: Pool ): Effect.Effect<{ flattenEtape: Partial<Pick<ApiFlattenEtape, 'id'>> & Omit<ApiFlattenEtape, 'id'>; perimetreInfos: PerimetreInfos }, CaminoError<GetFlattenEtapeErrors>> => { - const titreEtapeHeritage = titreEtapeHeritageBuild(etape.date, etape.typeId, demarche, titreTypeId, demarche.typeId, 'id' in etape ? etape.id : null) return Effect.Do.pipe( - Effect.bind('perimetreInfos', () => - getPerimetreInfosInternal(pool, etape.geojson4326Perimetre, etape.geojsonOriginePerimetre, etape.geojsonOriginePoints, titreTypeId, etape.geojsonOrigineGeoSystemeId, etape.geojsonOrigineForages) + Effect.bind('machineInfo', () => { + const machineInfo = MachineInfo.withMachineId(titreTypeId, demarche.typeId, demarche.id, demarche.machineId) + if (!machineInfo.valid) { + return Effect.fail({ message: incoherentMachineInfo, extra: machineInfo.error }) + } + + return Effect.succeed(machineInfo.value) + }), + Effect.let('titreEtapeHeritage', ({ machineInfo }) => titreEtapeHeritageBuild(etape.date, machineInfo, etape.typeId, demarche, 'id' in etape ? etape.id : null)), + + Effect.bind('perimetreInfos', ({ machineInfo }) => + getPerimetreInfosInternal(pool, etape.geojson4326Perimetre, etape.geojsonOriginePerimetre, etape.geojsonOriginePoints, machineInfo, etape.geojsonOrigineGeoSystemeId, etape.geojsonOrigineForages) ), - Effect.bind('heritageProps', () => + Effect.bind('heritageProps', ({ titreEtapeHeritage }) => Effect.succeed( ETAPE_HERITAGE_PROPS.reduce<IHeritageProps>((acc, propId) => { acc[propId] = { @@ -548,8 +583,8 @@ const getFlattenEtape = ( }, {} as IHeritageProps) ) ), - Effect.bind('heritageContenu', () => { - const sections = getSections(titreTypeId, demarche.typeId, etape.typeId) + Effect.bind('heritageContenu', ({ machineInfo, titreEtapeHeritage }) => { + const sections = getSections(machineInfo, etape.typeId) const heritageContenu = sections.reduce<IHeritageContenu>((accSections, section) => { accSections[section.id] = section.elements.reduce<NonNullable<IHeritageContenu[string]>>((accElements, element) => { @@ -566,8 +601,8 @@ const getFlattenEtape = ( return Effect.succeed(heritageContenu) }), Effect.let('fakeEtapeId', () => newEtapeId('newId')), - Effect.bind('flattenEtape', ({ perimetreInfos, heritageProps, heritageContenu, fakeEtapeId }) => - iTitreEtapeToFlattenEtape({ + Effect.bind('flattenEtape', ({ perimetreInfos, heritageProps, heritageContenu, fakeEtapeId, machineInfo }) => + iTitreEtapeToFlattenEtape(machineInfo, { ...etape, demarche, ...perimetreInfos, @@ -600,6 +635,8 @@ const droitsInsuffisants = 'droits insuffisants pour créer cette étape' as con const erreurLorsDeLaCreationDeLEtape = "Une erreur est survenue lors de la création de l'étape" as const const tachesAnnexes = 'une erreur est survenue lors des tâches annexes' as const const envoieMails = 'une erreur est survenue lors des envois de mail' as const +const etapesNonChargees = "la liste des étapes n'est pas chargée" as const +const demarchesNonChargees = "la liste des démarches n'est pas chargée" as const type CreateEtapeError = | GetFlattenEtapeErrors | EffectDbQueryAndValidateErrors @@ -614,6 +651,8 @@ type CreateEtapeError = | typeof erreurLorsDeLaCreationDeLEtape | typeof tachesAnnexes | typeof envoieMails + | typeof etapesNonChargees + | typeof demarchesNonChargees export const createEtape: RestNewPostCall<'/rest/etapes'> = (rootPipe): Effect.Effect<{ id: EtapeId }, CaminoApiError<CreateEtapeError>> => { return rootPipe.pipe( Effect.tap(({ body: etape, user }) => @@ -649,28 +688,45 @@ export const createEtape: RestNewPostCall<'/rest/etapes'> = (rootPipe): Effect.E userSuper ), catch: e => ({ message: demarcheExistePas, extra: e }), - }) + }).pipe( + Effect.filterOrFail( + (demarche): demarche is ITitreDemarche => isNotNullNorUndefined(demarche), + () => ({ message: demarcheExistePas }) + ), + Effect.filterOrFail( + (demarche): demarche is ITitreDemarche & { etapes: ITitreEtape[] } => isNotNullNorUndefined(demarche.etapes), + () => ({ message: etapesNonChargees }) + ) + ) ), - Effect.filterOrFail( - (value): value is typeof value & { titreDemarche: Omit<ITitreDemarche, 'titre'> & { titre: ITitre } } => - isNotNullNorUndefined(value.titreDemarche) && isNotNullNorUndefined(value.titreDemarche.titre), - () => ({ message: titreExistePas }) + Effect.bind('titre', ({ titreDemarche }) => + Effect.Do.pipe( + Effect.map(() => titreDemarche.titre), + Effect.filterOrFail( + (value): value is ITitre => isNotNullNorUndefined(value), + () => ({ message: titreExistePas }) + ), + Effect.filterOrFail( + (value): value is ITitre & { demarches: ITitreDemarche[] } => isNotNullNorUndefined(value.demarches), + () => ({ message: demarchesNonChargees }) + ) + ) ), Effect.let('isBrouillon', ({ body: etape }) => canBeBrouillon(etape.typeId)), Effect.filterOrFail( - ({ isBrouillon, titreDemarche, user, body: etape }) => - canCreateEtape(user, etape.typeId, isBrouillon, titreDemarche.titre.titulaireIds ?? [], titreDemarche.titre.administrationsLocales ?? [], titreDemarche.typeId, { - typeId: titreDemarche.titre.typeId, - titreStatutId: titreDemarche.titre.titreStatutId, + ({ isBrouillon, titreDemarche, titre, user, body: etape }) => + canCreateEtape(user, etape.typeId, isBrouillon, titre.titulaireIds ?? [], titre.administrationsLocales ?? [], titreDemarche.typeId, { + typeId: titre.typeId, + titreStatutId: titre.titreStatutId, }), () => ({ message: droitsInsuffisants }) ), - Effect.bind('hasTitreFrom', ({ titreDemarche, pool }) => hasTitreFrom(pool, titreDemarche.titre.id)), - Effect.bind('flattenEtapeAndPerimetreInfo', ({ titreDemarche, isBrouillon, body: etape, pool, hasTitreFrom }) => + Effect.bind('hasTitreFrom', ({ titre, pool }) => hasTitreFrom(pool, titre.id)), + Effect.bind('flattenEtapeAndPerimetreInfo', ({ titreDemarche, isBrouillon, titre, body: etape, pool, hasTitreFrom }) => getFlattenEtape( etape as RestEtapeCreation, // TODO 2024-11-14 comment on fait là, si on met le deepReadonly ça transpire partout et c'est violent :( titreDemarche, - titreDemarche.titre.typeId, + titre.typeId, isBrouillon, etapeSlugValidator.parse('unknown'), etape.typeId === ETAPES_TYPES.demande ? { amIFirst: true } : 'non-applicable', @@ -682,19 +738,23 @@ export const createEtape: RestNewPostCall<'/rest/etapes'> = (rootPipe): Effect.E Effect.bind('entrepriseDocuments', ({ flattenEtapeAndPerimetreInfo, body: etape, user, pool }) => validateAndGetEntrepriseDocuments(pool, flattenEtapeAndPerimetreInfo.flattenEtape, etape.entrepriseDocumentIds, user) ), - Effect.tap(({ flattenEtapeAndPerimetreInfo, titreDemarche, entrepriseDocuments, body: etape, user }) => { + Effect.let('machineInfo', ({ body: etape, titre, titreDemarche }) => { const firstEtapeDate = demarcheEnregistrementDemandeDateFind(titreDemarche.etapes) + const value = isNotNullNorUndefined(firstEtapeDate) ? firstEtapeDate : firstEtapeDateValidator.parse(etape.date) + return MachineInfo.withDate(titre.typeId, titreDemarche.typeId, titreDemarche.id, value) + }), + Effect.tap(({ flattenEtapeAndPerimetreInfo, titreDemarche, titre, entrepriseDocuments, body: etape, user, machineInfo }) => { const rulesErrors = titreEtapeUpdationValidate( flattenEtapeAndPerimetreInfo.flattenEtape, - titreDemarche, - titreDemarche.titre, + titreDemarche.etapes, + titre.demarches, etape.etapeDocuments, etape.etapeAvis, entrepriseDocuments, flattenEtapeAndPerimetreInfo.perimetreInfos.sdomZones, flattenEtapeAndPerimetreInfo.perimetreInfos.communes.map(({ id }) => id), user, - isNotNullNorUndefined(firstEtapeDate) ? firstEtapeDate : firstEtapeDateValidator.parse(etape.date) + machineInfo ) if (isNotNullNorUndefinedNorEmpty(rulesErrors)) { return Effect.fail({ message: etapeNonValide, detail: rulesErrors.join(', ') }) @@ -728,10 +788,10 @@ export const createEtape: RestNewPostCall<'/rest/etapes'> = (rootPipe): Effect.E }) ), - Effect.tap(({ etapeUpdated, titreDemarche, user, pool }) => + Effect.tap(({ etapeUpdated, titreDemarche, titre, user, pool }) => Effect.tryPromise({ try: async () => { - await titreEtapeAdministrationsEmailsSend(etapeUpdated, titreDemarche.typeId, titreDemarche.titreId, titreDemarche.titre.typeId, user) + await titreEtapeAdministrationsEmailsSend(etapeUpdated, titreDemarche.typeId, titreDemarche.titreId, titre.typeId, user) await titreEtapeUtilisateursEmailsSend(etapeUpdated, titreDemarche.titreId, pool) }, catch: e => ({ message: envoieMails, extra: e }), @@ -765,11 +825,12 @@ export const createEtape: RestNewPostCall<'/rest/etapes'> = (rootPipe): Effect.E "impossible d'insérer un fichier en base", 'Une erreur inattendue est survenue lors de la récupération des informations geojson en base', 'Impossible de transformer la feature collection', - 'pas de démarche chargée', - 'pas de démarche ou de titre chargé', "pas d'héritage chargé", 'pas de slug', 'Les données en base ne correspondent pas à ce qui est attendu', + 'La machine associée à la démarche est incohérente', + "la liste des étapes n'est pas chargée", + "la liste des démarches n'est pas chargée", () => ({ ...caminoError, status: HTTP_STATUS.INTERNAL_SERVER_ERROR }) ), Match.exhaustive @@ -802,6 +863,9 @@ type UpdateEtapeErrors = | InsertEtapeDocumentsErrors | UpdateEtapeDocumentsErrors | UpdateEtapeAvisErrors + | typeof etapesNonChargees + | typeof demarchesNonChargees + | typeof titreExistePas export const updateEtape: RestNewPutCall<'/rest/etapes'> = (rootPipe): Effect.Effect<{ id: EtapeId }, CaminoApiError<UpdateEtapeErrors>> => { return rootPipe.pipe( Effect.let('etape', ({ body }) => body), @@ -828,22 +892,6 @@ export const updateEtape: RestNewPutCall<'/rest/etapes'> = (rootPipe): Effect.Ef isNotNullNorUndefined(value.demarche) && isNotNullNorUndefined(value.demarche.titre) && value.demarche.titre.administrationsLocales !== undefined, () => ({ message: demarcheNonChargee }) ), - Effect.filterOrFail( - titreEtapeOld => - canEditEtape( - user, - titreEtapeOld.typeId, - titreEtapeOld.isBrouillon, - titreEtapeOld.titulaireIds ?? [], - titreEtapeOld.demarche.titre.administrationsLocales ?? [], - titreEtapeOld.demarche.typeId, - { - typeId: titreEtapeOld.demarche.titre.typeId, - titreStatutId: titreEtapeOld.demarche.titre.titreStatutId, - } - ), - () => ({ message: droitsInsuffisantsUpdate }) - ), Effect.filterOrFail( titreEtapeOld => titreEtapeOld.typeId === etape.typeId, () => ({ message: interditTypeEtapeEdition }) @@ -875,24 +923,42 @@ export const updateEtape: RestNewPutCall<'/rest/etapes'> = (rootPipe): Effect.Ef catch: e => ({ message: demarcheExistePas, extra: e }), }).pipe( Effect.filterOrFail( - (value): value is ITitreDemarche & { titre: ITitre } => isNotNullNorUndefined(value) && isNotNullNorUndefined(value.titre), + (demarche): demarche is ITitreDemarche => isNotNullNorUndefined(demarche), () => ({ message: demarcheExistePas }) ), Effect.filterOrFail( - value => isNotNullNorUndefined(value.titre.titulaireIds) && isNotNullNorUndefined(value.titre.amodiataireIds), - () => ({ message: demarcheNonChargee }) + (demarche): demarche is ITitreDemarche & { etapes: ITitreEtape[] } => isNotNullNorUndefined(demarche.etapes), + () => ({ message: etapesNonChargees }) ) ) ), - Effect.let('titreTypeId', ({ titreDemarche }) => titreDemarche.titre.typeId), - Effect.let('isBrouillon', ({ titreEtapeOld }) => titreEtapeOld.isBrouillon), - - Effect.bind('flattenEtapeAndPerimetre', ({ etape, titreDemarche, titreTypeId, isBrouillon, titreEtapeOld, pool }) => + Effect.bind('titre', ({ titreDemarche }) => + Effect.Do.pipe( + Effect.map(() => titreDemarche.titre), + Effect.filterOrFail( + (value): value is ITitre => isNotNullNorUndefined(value), + () => ({ message: titreExistePas }) + ), + Effect.filterOrFail( + (value): value is ITitre & { demarches: ITitreDemarche[] } => isNotNullNorUndefined(value.demarches), + () => ({ message: demarchesNonChargees }) + ) + ) + ), + Effect.filterOrFail( + ({ titreEtapeOld, titre, user }) => + canEditEtape(user, titreEtapeOld.typeId, titreEtapeOld.isBrouillon, titre.titulaireIds ?? [], titreEtapeOld.demarche.titre.administrationsLocales ?? [], titreEtapeOld.demarche.typeId, { + typeId: titreEtapeOld.demarche.titre.typeId, + titreStatutId: titreEtapeOld.demarche.titre.titreStatutId, + }), + () => ({ message: droitsInsuffisantsUpdate }) + ), + Effect.bind('flattenEtapeAndPerimetre', ({ etape, titreDemarche, titre, titreEtapeOld, pool }) => getFlattenEtape( etape as RestEtapeModification, // TODO 2024-11-14 comment on fait là, si on met le deepReadonly ça transpire partout et c'est violent :( titreDemarche, - titreTypeId, - isBrouillon, + titre.typeId, + titreEtapeOld.isBrouillon, titreEtapeOld.slug, titreEtapeOld.concurrence, titreEtapeOld.hasTitreFrom, @@ -903,23 +969,23 @@ export const updateEtape: RestNewPutCall<'/rest/etapes'> = (rootPipe): Effect.Ef Effect.bind('entrepriseDocuments', ({ pool, flattenEtapeAndPerimetre, etape, user }) => validateAndGetEntrepriseDocuments(pool, flattenEtapeAndPerimetre.flattenEtape, etape.entrepriseDocumentIds, user) ), - Effect.let('firstEtapeDate', ({ titreDemarche, etape }) => { + Effect.let('machineInfo', ({ body: etape, titreDemarche, titre }) => { const firstEtapeDate = demarcheEnregistrementDemandeDateFind(titreDemarche.etapes) - - return isNotNullNorUndefined(firstEtapeDate) ? firstEtapeDate : firstEtapeDateValidator.parse(etape.date) + const value = isNotNullNorUndefined(firstEtapeDate) ? firstEtapeDate : firstEtapeDateValidator.parse(etape.date) + return MachineInfo.withDate(titre.typeId, titreDemarche.typeId, titreDemarche.id, value) }), - Effect.tap(({ flattenEtapeAndPerimetre, titreDemarche, entrepriseDocuments, etape, user, titreEtapeOld, firstEtapeDate }) => { + Effect.tap(({ flattenEtapeAndPerimetre, titre, titreDemarche, entrepriseDocuments, etape, user, titreEtapeOld, machineInfo }) => { const rulesErrors = titreEtapeUpdationValidate( flattenEtapeAndPerimetre.flattenEtape, - titreDemarche, - titreDemarche.titre, + titreDemarche.etapes, + titre.demarches, etape.etapeDocuments, etape.etapeAvis, entrepriseDocuments, flattenEtapeAndPerimetre.perimetreInfos.sdomZones, flattenEtapeAndPerimetre.perimetreInfos.communes.map(({ id }) => id), user, - firstEtapeDate, + machineInfo, titreEtapeOld ) if (isNotNullNorUndefinedNorEmpty(rulesErrors)) { @@ -928,7 +994,7 @@ export const updateEtape: RestNewPutCall<'/rest/etapes'> = (rootPipe): Effect.Ef return Effect.succeed(null) }), Effect.tap(({ etape, pool }) => checkEntreprisesExist(pool, [...etape.titulaireIds, ...etape.amodiataireIds])), - Effect.bind('etapeUpdated', ({ etape, flattenEtapeAndPerimetre, titreEtapeOld, user, titreDemarche, isBrouillon }) => + Effect.bind('etapeUpdated', ({ etape, flattenEtapeAndPerimetre, titreEtapeOld, user, titreDemarche }) => Effect.tryPromise({ try: async () => { const value = await titreEtapeUpsert( @@ -936,7 +1002,7 @@ export const updateEtape: RestNewPutCall<'/rest/etapes'> = (rootPipe): Effect.Ef ...etape, statutId: getStatutId(flattenEtapeAndPerimetre.flattenEtape, getCurrent()), ...flattenEtapeAndPerimetre.perimetreInfos, - isBrouillon, + isBrouillon: titreEtapeOld.isBrouillon, demarcheIdsConsentement: titreEtapeOld.demarcheIdsConsentement, }, user, @@ -953,18 +1019,15 @@ export const updateEtape: RestNewPutCall<'/rest/etapes'> = (rootPipe): Effect.Ef Effect.tap(({ pool, etapeUpdated, etape }) => updateEtapeDocuments(pool, etapeUpdated.id, etape.etapeDocuments)), Effect.tap(({ pool, etapeUpdated }) => deleteTitreEtapeEntrepriseDocument(pool, { titre_etape_id: etapeUpdated.id })), Effect.tap(({ pool, etapeUpdated, entrepriseDocuments }) => insertTitreEtapeEntrepriseDocuments(pool, etapeUpdated.id, entrepriseDocuments)), - Effect.tap(({ pool, isBrouillon, etapeUpdated, etape, titreTypeId, titreDemarche, flattenEtapeAndPerimetre, firstEtapeDate }) => + Effect.tap(({ pool, titreEtapeOld, etapeUpdated, etape, flattenEtapeAndPerimetre, machineInfo }) => updateEtapeAvis( pool, etapeUpdated.id, - isBrouillon, + titreEtapeOld.isBrouillon, etape.etapeAvis, etape.typeId, flattenEtapeAndPerimetre.flattenEtape.contenu, - titreTypeId, - titreDemarche.typeId, - titreDemarche.id, - firstEtapeDate, + machineInfo, flattenEtapeAndPerimetre.perimetreInfos.communes.map(({ id }) => id) ) ), @@ -974,16 +1037,16 @@ export const updateEtape: RestNewPutCall<'/rest/etapes'> = (rootPipe): Effect.Ef catch: e => ({ message: tachesAnnexes, extra: e }), }) ), - Effect.tap(({ titreDemarche, titreEtapeOld, flattenEtapeAndPerimetre, user }) => + Effect.tap(({ titreDemarche, titreEtapeOld, flattenEtapeAndPerimetre, user, titre }) => Effect.tryPromise({ - try: () => titreEtapeAdministrationsEmailsSend(flattenEtapeAndPerimetre.flattenEtape, titreDemarche.typeId, titreDemarche.titreId, titreDemarche.titre.typeId, user, titreEtapeOld), + try: () => titreEtapeAdministrationsEmailsSend(flattenEtapeAndPerimetre.flattenEtape, titreDemarche.typeId, titreDemarche.titreId, titre.typeId, user, titreEtapeOld), catch: e => ({ message: envoieMails, extra: e }), }) ), Effect.map(({ titreEtapeOld }) => ({ id: titreEtapeOld.id })), Effect.mapError(caminoError => Match.value(caminoError.message).pipe( - Match.whenOr("la démarche n'existe pas", "L'étape n'existe pas", () => ({ ...caminoError, status: HTTP_STATUS.NOT_FOUND })), + Match.whenOr("la démarche n'existe pas", "L'étape n'existe pas", "le titre n'existe pas", () => ({ ...caminoError, status: HTTP_STATUS.NOT_FOUND })), Match.whenOr( "l'étape n'est pas valide", "certaines entreprises n'existent pas", @@ -1011,11 +1074,12 @@ export const updateEtape: RestNewPutCall<'/rest/etapes'> = (rootPipe): Effect.Ef "impossible d'insérer un fichier en base", 'Une erreur inattendue est survenue lors de la récupération des informations geojson en base', 'Impossible de transformer la feature collection', - 'pas de démarche chargée', - 'pas de démarche ou de titre chargé', "pas d'héritage chargé", 'pas de slug', 'Les données en base ne correspondent pas à ce qui est attendu', + 'La machine associée à la démarche est incohérente', + "la liste des étapes n'est pas chargée", + "la liste des démarches n'est pas chargée", () => ({ ...caminoError, status: HTTP_STATUS.INTERNAL_SERVER_ERROR }) ), Match.exhaustive @@ -1048,6 +1112,7 @@ type DeposeEtapeErrors = | typeof impossibleDeRecupererLEtapeApresMaj | typeof impossibleDeMajLEtape | typeof envoieMails + | typeof incoherentMachineInfo | EffectDbQueryAndValidateErrors | GetGeojsonInformationErrorMessages | TitreEtapeToFlattenEtapeErrors @@ -1095,7 +1160,7 @@ export const deposeEtape: RestNewPutCall<'/rest/etapes/:etapeId/depot'> = (rootP Effect.bind('titre', ({ titreDemarche }) => Effect.succeed(titreDemarche.titre).pipe( Effect.filterOrFail( - titre => isNotNullNorUndefined(titre), + (titre): titre is NonNullable<ITitre> => isNotNullNorUndefined(titre), () => ({ message: titreNonExistant }) ), Effect.filterOrFail( @@ -1143,8 +1208,15 @@ export const deposeEtape: RestNewPutCall<'/rest/etapes/:etapeId/depot'> = (rootP } ) ), - Effect.bind('flattenEtape', ({ titreEtape }) => iTitreEtapeToFlattenEtape(titreEtape)), - Effect.let('firstEtapeDate', ({ titreDemarche }) => demarcheEnregistrementDemandeDateFind(titreDemarche.etapes)), + Effect.bind('machineInfo', ({ titreDemarche, titre }) => { + const machineInfo = MachineInfo.withMachineId(titre.typeId, titreDemarche.typeId, titreDemarche.id, titreDemarche.machineId) + if (!machineInfo.valid) { + return Effect.fail({ message: incoherentMachineInfo, extra: machineInfo.error }) + } + + return Effect.succeed(machineInfo.value) + }), + Effect.bind('flattenEtape', ({ titreEtape, machineInfo }) => iTitreEtapeToFlattenEtape(machineInfo, titreEtape)), Effect.let('date', ({ user, titreEtape }) => (isEntreprise(user) || isBureauDEtudes(user) ? getCurrent() : titreEtape.date)), Effect.bind('sdomEtCommunes', ({ titreEtape, pool }) => { if (isNotNullNorUndefined(titreEtape.geojson4326Perimetre)) { @@ -1156,19 +1228,17 @@ export const deposeEtape: RestNewPutCall<'/rest/etapes/:etapeId/depot'> = (rootP return Effect.succeed(emptyResult) }), Effect.filterOrFail( - ({ user, titre, titreDemarche, flattenEtape, etapeDocuments, entrepriseDocuments, sdomEtCommunes, etapeAvis, firstEtapeDate, date }) => + ({ user, titre, flattenEtape, etapeDocuments, entrepriseDocuments, sdomEtCommunes, etapeAvis, machineInfo }) => canDeposeEtape( user, + machineInfo, { ...titre, titulaires: titre.titulaireIds ?? [], administrationsLocales: titre.administrationsLocales ?? [] }, - titreDemarche.id, - titreDemarche.typeId, flattenEtape, etapeDocuments, entrepriseDocuments, sdomEtCommunes.sdomZones, sdomEtCommunes.communes, - etapeAvis, - isNotNullNorUndefined(firstEtapeDate) ? firstEtapeDate : firstEtapeDateValidator.parse(date) + etapeAvis ), () => ({ message: droitsInsuffisantsDeposeEtape }) ), @@ -1241,14 +1311,13 @@ export const deposeEtape: RestNewPutCall<'/rest/etapes/:etapeId/depot'> = (rootP 'Problème de validation de données', 'Une erreur inattendue est survenue lors de la récupération des informations geojson en base', "pas d'héritage chargé", - 'pas de démarche chargée', - 'pas de démarche ou de titre chargé', 'pas de slug', 'une erreur est survenue lors des envois de mail', 'une erreur est survenue lors des tâches annexes', "une erreur s'est produite lors de la vérification des droits de lecture d'un avis", "une erreur s'est produite lors de la vérification des droits de lecture d'un document", "Impossible de transformer le document en base en document d'API", + 'La machine associée à la démarche est incohérente', () => ({ ...caminoError, status: HTTP_STATUS.INTERNAL_SERVER_ERROR }) ), Match.exhaustive @@ -1273,6 +1342,7 @@ export const getEtapesTypesEtapesStatusWithMainStep: RestNewGetCall<'/rest/etape "impossible de récupérer l'étape", 'impossible de récupérer la démarche', 'Les données en base ne correspondent pas à ce qui est attendu', + 'La machine associée à la démarche est incohérente', () => ({ ...caminoError, status: HTTP_STATUS.INTERNAL_SERVER_ERROR }) ), Match.exhaustive @@ -1297,6 +1367,7 @@ type DemarcheEtapesTypesGetErrors = | typeof impossibleDeRecupererLEtape | typeof etapeNonExistante | typeof impossibleDeRecupererLesEtapesTypes + | typeof incoherentMachineInfo const demarcheEtapesTypesGet = ( titreDemarcheId: DemarcheId, date: CaminoDate, @@ -1322,19 +1393,30 @@ const demarcheEtapesTypesGet = ( userSuper ), catch: e => ({ message: impossibleDeRecupererLaDemarche, extra: e }), - }) - ), - Effect.filterOrFail( - (result): result is NotNullableKeys<typeof result> => isNotNullNorUndefined(result.titreDemarche), - () => ({ message: demarcheInexistante }) + }).pipe( + Effect.filterOrFail( + (demarche): demarche is ITitreDemarche => isNotNullNorUndefined(demarche), + () => ({ message: demarcheInexistante }) + ) + ) ), - Effect.filterOrFail( - (result): result is NotNullableKeys<typeof result> & { titreDemarche: { titre: ITitre } } => isNotNullNorUndefined(result.titreDemarche.titre?.titulaireIds), - () => ({ message: demarcheIncomplete }) + Effect.bind('titre', ({ titreDemarche }) => + Effect.Do.pipe( + Effect.map(() => titreDemarche.titre), + Effect.filterOrFail( + (titre): titre is ITitre => isNotNullNorUndefined(titre), + () => ({ message: demarcheIncomplete }) + ) + ) ), - Effect.filterOrFail( - ({ titreDemarche }) => isNotNullNorUndefined(titreDemarche.etapes), - () => ({ message: etapeNonChargees }) + Effect.bind('etapes', ({ titreDemarche }) => + Effect.Do.pipe( + Effect.map(() => titreDemarche.etapes), + Effect.filterOrFail( + (etapes): etapes is ITitreEtape[] => isNotNullNorUndefined(etapes), + () => ({ message: etapeNonChargees }) + ) + ) ), Effect.bind('etape', () => Effect.tryPromise({ @@ -1352,33 +1434,45 @@ const demarcheEtapesTypesGet = ( ({ etape }) => isNullOrUndefined(titreEtapeId) || (isNotNullNorUndefined(titreEtapeId) && isNotNullNorUndefined(etape)), () => ({ message: etapeNonExistante }) ), - Effect.let('firstEtapeDate', ({ titreDemarche }) => demarcheEnregistrementDemandeDateFind(titreDemarche.etapes)), - Effect.let('machine', ({ titreDemarche, firstEtapeDate }) => - machineFind(titreDemarche.titre.typeId, titreDemarche.typeId, titreDemarche.id, isNotNullNorUndefined(firstEtapeDate) ? firstEtapeDate : firstEtapeDateValidator.parse(date)) - ), + Effect.bind('machine', ({ etapes, titre, titreDemarche }) => { + if (isNullOrUndefinedOrEmpty(etapes)) { + return Effect.succeed(new ApiMachineInfo(MachineInfo.withDate(titre.typeId, titreDemarche.typeId, titreDemarche.id, firstEtapeDateValidator.parse(date)))) + } + const newDateMachine = demarcheEnregistrementDemandeDateFind( + etapes.map(etape => { + if (etape.id === titreEtapeId) { + return { ...etape, date: date } + } + + return etape + }) + ) + if (isNotNullNorUndefined(newDateMachine)) { + return Effect.succeed(new ApiMachineInfo(MachineInfo.withDate(titre.typeId, titreDemarche.typeId, titreDemarche.id, newDateMachine))) + } + + const machineInfo = MachineInfo.withMachineId(titre.typeId, titreDemarche.typeId, titreDemarche.id, titreDemarche.machineId) + if (!machineInfo.valid) { + return Effect.fail({ message: incoherentMachineInfo, extra: machineInfo.error }) + } + + return Effect.succeed(new ApiMachineInfo(machineInfo.value)) + }), Effect.bind('etapesTypes', ({ machine, titreDemarche, etape }) => Effect.try({ try: () => { - const etapesTypes: EtapeTypeEtapeStatutWithMainStep = getPossiblesEtapesTypes( - machine, - titreDemarche.titre.typeId, - titreDemarche.typeId, - etape?.typeId, - titreEtapeId ?? undefined, - date, - titreDemarche.etapes ?? [] - ) + const etapesTypes: EtapeTypeEtapeStatutWithMainStep = getPossiblesEtapesTypes(machine, etape?.typeId, titreEtapeId ?? undefined, date, titreDemarche.etapes ?? []) return etapesTypes }, catch: e => ({ message: impossibleDeRecupererLesEtapesTypes, extra: e }), }) ), - Effect.map(({ etapesTypes, titreDemarche }) => + Effect.map(({ etapesTypes, titreDemarche, titre }) => getKeys(etapesTypes, isEtapeTypeId).reduce<EtapeTypeEtapeStatutWithMainStep>((acc, etapeTypeId) => { if ( - canCreateEtape(user, etapeTypeId, ETAPE_IS_BROUILLON, titreDemarche.titre.titulaireIds ?? [], titreDemarche.titre.administrationsLocales ?? [], titreDemarche.typeId, { - typeId: titreDemarche.titre.typeId, - titreStatutId: titreDemarche.titre.titreStatutId, + canCreateEtape(user, etapeTypeId, ETAPE_IS_BROUILLON, titre.titulaireIds ?? [], titre.administrationsLocales ?? [], titreDemarche.typeId, { + typeId: titre.typeId, + titreStatutId: titre.titreStatutId, }) ) { acc[etapeTypeId] = etapesTypes[etapeTypeId] diff --git a/packages/api/src/api/rest/format/titres.ts b/packages/api/src/api/rest/format/titres.ts index e852d4c91..91f8e17fa 100644 --- a/packages/api/src/api/rest/format/titres.ts +++ b/packages/api/src/api/rest/format/titres.ts @@ -25,6 +25,7 @@ import { GetEntreprises, getEntreprises } from '../entreprises.queries' import { EntrepriseId } from 'camino-common/src/entreprise' import { slugify } from 'camino-common/src/strings' import { callAndExit } from '../../../tools/fp-tools' +import { MachineInfo } from 'camino-common/src/machines' const getFacadesMaritimeCell = (secteursMaritime: SecteursMaritimes[], separator: string): string => getFacadesComputed(secteursMaritime) @@ -37,9 +38,16 @@ const titreContenuTableFormat = (titre: ITitre): Record<string, string> => { if (isNullOrUndefinedOrEmpty(orderedDemarches)) { return {} } + // TODO 2025-03-27: ne pas prendre la première démarche mais la dernière démarche valide avec infos publiques (?) const demarche = orderedDemarches[0] + const machineInfo = MachineInfo.withMachineId(titre.typeId, demarche.typeId, demarche.id, demarche.machineId) + if (!machineInfo.valid) { + console.error(`La machine associée à la démarche est invalide : ${machineInfo.error}`) + return {} + } + const etapes = (demarche.etapes ?? []).map(etape => { - const sections = getSections(titre.typeId, demarche.typeId, etape.typeId) + const sections = getSections(machineInfo.value, etape.typeId) .map(section => ({ ...section, elements: section.elements.filter(element => !(etape.heritageContenu?.[section.id]?.[element.id]?.actif ?? false)) })) .filter(section => section.elements.length > 0) diff --git a/packages/api/src/api/rest/index.test.integration.ts b/packages/api/src/api/rest/index.test.integration.ts index 932304974..f3e418408 100644 --- a/packages/api/src/api/rest/index.test.integration.ts +++ b/packages/api/src/api/rest/index.test.integration.ts @@ -59,6 +59,7 @@ beforeAll(async () => { id: demarcheId, titreId: titreId, typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: null, etapes: [ { id: etapeId, diff --git a/packages/api/src/api/rest/perimetre.test.integration.ts b/packages/api/src/api/rest/perimetre.test.integration.ts index 64aaeb1d0..d2c644c90 100644 --- a/packages/api/src/api/rest/perimetre.test.integration.ts +++ b/packages/api/src/api/rest/perimetre.test.integration.ts @@ -1724,6 +1724,7 @@ describe('getPerimetreInfosByEtape', () => { propsTitreEtapesIds: { titulaires: 'titre-id-demarche-id-dpu', points: 'titre-id-demarche-id-dpu' }, demarches: [ { + machineId: null, id: newDemarcheId('titre-id-demarche-id'), titreId: newTitreId('titre-id'), typeId: 'oct', @@ -1783,6 +1784,7 @@ describe('getPerimetreInfosByDemarche', () => { propsTitreEtapesIds: { titulaires: 'titre-id-demarche-id-dpu', points: 'titre-id-demarche-id-dpu' }, demarches: [ { + machineId: null, id: demarcheId, titreId: newTitreId('titre-id'), typeId: 'oct', @@ -1837,6 +1839,7 @@ describe('getPerimetreInfosByDemarche', () => { propsTitreEtapesIds: { titulaires: 'titre-id-demarche-id-dpu', points: 'titre-id-demarche-id-dpu' }, demarches: [ { + machineId: null, id: demarcheId, titreId: newTitreId('titre-id'), typeId: 'oct', diff --git a/packages/api/src/api/rest/rest-test-utils.ts b/packages/api/src/api/rest/rest-test-utils.ts index 6f8f1669e..c91c27647 100644 --- a/packages/api/src/api/rest/rest-test-utils.ts +++ b/packages/api/src/api/rest/rest-test-utils.ts @@ -1,4 +1,4 @@ -import { CaminoDate, toCaminoDate } from 'camino-common/src/date' +import { CaminoDate, firstEtapeDateValidator, toCaminoDate } from 'camino-common/src/date' import { DemarcheId } from 'camino-common/src/demarche' import { EtapeBrouillon, EtapeId } from 'camino-common/src/etape' import { EtapeTypeId, canBeBrouillon } from 'camino-common/src/static/etapesTypes' @@ -7,6 +7,8 @@ import { isNotNullNorUndefined } from 'camino-common/src/typescript-tools' import { TitreId } from 'camino-common/src/validators/titres' import { insertTitreGraph } from '../../../tests/integration-test-helper' import { newDemarcheId, newEtapeId, newTitreId } from '../../database/models/_format/id-create' +import { MachineInfo } from 'camino-common/src/machines' +import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes' export async function etapeCreate( typeId?: EtapeTypeId, @@ -32,8 +34,8 @@ export async function etapeCreate( { id: demarcheId, titreId: titreId, - typeId: 'oct', - + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: MachineInfo.withDate(titreTypeId, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse(date)).machineId ?? null, etapes: [ { id: etapeId, diff --git a/packages/api/src/api/rest/titre-demande.queries.ts b/packages/api/src/api/rest/titre-demande.queries.ts index 9633e3e9d..6ce330e92 100644 --- a/packages/api/src/api/rest/titre-demande.queries.ts +++ b/packages/api/src/api/rest/titre-demande.queries.ts @@ -12,6 +12,10 @@ import { ICreateTitreDemarcheInternalQuery, ICreateTitreInternalQuery } from './ import { TitreDemande } from 'camino-common/src/titres.js' import { DemarcheId, DemarcheSlug } from 'camino-common/src/demarche.js' import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes.js' +import { CaminoMachineId } from 'camino-common/src/validators/machine.js' +import { MachineInfo } from 'camino-common/src/machines.js' +import { TitreTypeId } from 'camino-common/src/static/titresTypes.js' +import { firstEtapeDateValidator, getCurrent } from 'camino-common/src/date.js' type CreateTitreInput = Omit<TitreDemande, 'titreFromIds' | 'entrepriseId'> @@ -39,22 +43,25 @@ INSERT INTO titres (id, slug, nom, type_id, "references") VALUES ($ id !, $slug!, $ nom !, $ titreTypeId!, $references!) ` -const creationDemarcheImpossible = 'Création de la démarche impossible' as const -export type CreateDemarcheErrors = EffectDbQueryAndValidateErrors | 'Accès interdit' | typeof creationDemarcheImpossible -export const createDemarche = (pool: Pool, titreId: TitreId, demarcheTypeId: DemarcheTypeId): Effect.Effect<DemarcheId, CaminoError<CreateDemarcheErrors>> => { +export type CreateDemarcheErrors = EffectDbQueryAndValidateErrors +export const createDemarche = ( + pool: Pool, + titreId: TitreId, + titreTypeId: TitreTypeId, + demarcheTypeId: DemarcheTypeId, + description: string = '' +): Effect.Effect<DemarcheId, CaminoError<CreateDemarcheErrors>> => { return Effect.Do.pipe( - Effect.bind('id', () => Effect.succeed(newDemarcheId())), - Effect.bind('slug', () => - Effect.try({ - try: () => newDemarcheSlug(titreId, demarcheTypeId), - catch: unknown => ({ message: creationDemarcheImpossible, extra: unknown }), - }) - ), - Effect.tap(({ id, slug }) => effectDbQueryAndValidate(createTitreDemarcheInternal, { id, slug, titre_id: titreId, demarcheTypeId }, pool, z.void())), + Effect.let('id', () => newDemarcheId()), + Effect.let('slug', () => newDemarcheSlug(titreId, demarcheTypeId)), + Effect.let('machineId', ({ id }) => MachineInfo.withDate(titreTypeId, demarcheTypeId, id, firstEtapeDateValidator.parse(getCurrent())).machineId ?? null), + Effect.tap(({ id, slug, machineId }) => effectDbQueryAndValidate(createTitreDemarcheInternal, { id, slug, titre_id: titreId, demarcheTypeId, machineId, description }, pool, z.void())), Effect.map(({ id }) => id) ) } -const createTitreDemarcheInternal = sql<Redefine<ICreateTitreDemarcheInternalQuery, { id: DemarcheId; slug: DemarcheSlug; titre_id: TitreId; demarcheTypeId: DemarcheTypeId }, void>>` -INSERT INTO titres_demarches (id, slug, titre_id, type_id) - VALUES ($ id !, $slug!, $ titre_id !, $demarcheTypeId) +const createTitreDemarcheInternal = sql< + Redefine<ICreateTitreDemarcheInternalQuery, { id: DemarcheId; slug: DemarcheSlug; titre_id: TitreId; demarcheTypeId: DemarcheTypeId; machineId: CaminoMachineId | null; description: string }, void> +>` +INSERT INTO titres_demarches (id, slug, titre_id, type_id, machine_id, description) + VALUES ($ id !, $slug!, $ titre_id !, $demarcheTypeId!, $machineId!, $description) ` diff --git a/packages/api/src/api/rest/titre-demande.queries.types.ts b/packages/api/src/api/rest/titre-demande.queries.types.ts index 04d202f4c..fb3fbfcfb 100644 --- a/packages/api/src/api/rest/titre-demande.queries.types.ts +++ b/packages/api/src/api/rest/titre-demande.queries.types.ts @@ -21,8 +21,10 @@ export interface ICreateTitreInternalQuery { /** 'CreateTitreDemarcheInternal' parameters type */ export interface ICreateTitreDemarcheInternalParams { - demarcheTypeId?: string | null | void; + demarcheTypeId: string; + description?: string | null | void; id: string; + machineId: string; slug: string; titre_id: string; } diff --git a/packages/api/src/api/rest/titre-demande.ts b/packages/api/src/api/rest/titre-demande.ts index 6cfa6427f..77dcd9a79 100644 --- a/packages/api/src/api/rest/titre-demande.ts +++ b/packages/api/src/api/rest/titre-demande.ts @@ -22,6 +22,7 @@ import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' import { ETAPES_STATUTS } from 'camino-common/src/static/etapesStatuts' import { TITRES_TYPES_IDS } from 'camino-common/src/static/titresTypes' import { updateUtilisateurTitre } from './titres.queries' +import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes' type TitreDemandeCreerErrors = | 'Accès interdit' @@ -90,7 +91,7 @@ export const titreDemandeCreer: RestNewPostCall<'/rest/titres'> = (rootPipe): Ef catch: unknown => ({ message: 'Problème lors de la mise à jour des taches du titre' as const, extra: unknown }), }) ), - Effect.bind('demarcheId', ({ titreId, pool }) => createDemarche(pool, titreId, 'oct')), + Effect.bind('demarcheId', ({ titreId, pool, titreDemande }) => createDemarche(pool, titreId, titreDemande.titreTypeId, DEMARCHES_TYPES_IDS.Octroi)), Effect.tap(({ titreId, demarcheId, pool }) => { return Effect.tryPromise({ try: async () => { @@ -161,7 +162,6 @@ export const titreDemandeCreer: RestNewPostCall<'/rest/titres'> = (rootPipe): Ef 'Création du titre impossible', "Impossible d'exécuter la requête dans la base de données", 'Problème lors de la mise à jour des taches du titre', - 'Création de la démarche impossible', 'Problème lors de la mise à jour des taches de la démarche', "Problème lors de la création de l'étape", "Problème lors de la mise à jour des tâches de l'étape", diff --git a/packages/api/src/api/rest/titres.queries.ts b/packages/api/src/api/rest/titres.queries.ts index aece42351..099b0a5c2 100644 --- a/packages/api/src/api/rest/titres.queries.ts +++ b/packages/api/src/api/rest/titres.queries.ts @@ -12,7 +12,7 @@ import { IGetTitresDbQuery, IGetTitulairesAmodiatairesByTitreIdDbQuery, } from './titres.queries.types' -import { caminoDateValidator, firstEtapeDateValidator } from 'camino-common/src/date' +import { caminoDateValidator } from 'camino-common/src/date' import { z } from 'zod' import { Commune, communeIdValidator } from 'camino-common/src/static/communes' import { Pool } from 'pg' @@ -20,16 +20,7 @@ import { titreTypeIdValidator } from 'camino-common/src/static/titresTypes' import { isAdministration, isSuper, User, UtilisateurId } from 'camino-common/src/roles' import { titreStatutIdValidator } from 'camino-common/src/static/titresStatuts' import { titreReferenceValidator } from 'camino-common/src/titres-references' -import { - demarcheEnregistrementDemandeDateFind, - DemarcheEtape, - DemarcheEtapeCommon, - DemarcheEtapeFondamentale, - DemarcheEtapeNonFondamentale, - DemarcheId, - demarcheIdValidator, - demarcheSlugValidator, -} from 'camino-common/src/demarche' +import { DemarcheEtape, DemarcheEtapeCommon, DemarcheEtapeFondamentale, DemarcheEtapeNonFondamentale, DemarcheId, demarcheIdValidator, demarcheSlugValidator } from 'camino-common/src/demarche' import { demarcheStatutIdValidator } from 'camino-common/src/static/demarchesStatuts' import { demarcheTypeIdValidator } from 'camino-common/src/static/demarchesTypes' import { getDemarcheByIdOrSlug, getEtapesByDemarcheId } from './demarches.queries' @@ -57,9 +48,17 @@ import { Effect } from 'effect' import { CaminoError } from 'camino-common/src/zod-tools' import { getAvisTypes } from 'camino-common/src/avisTypes' import { isArmMecanise } from 'camino-common/src/static/mecanise' +import { MachineInfo } from 'camino-common/src/machines' +import { machineIdValidator } from 'camino-common/src/validators/machine' type SuperEtapeDemarcheTitreGet = OmitDistributive<DemarcheEtape, 'etape_documents' | 'avis_documents'> -type SuperDemarcheTitreGet = Omit<TitreGet['demarches'][0], 'etapes'> & { etapes: SuperEtapeDemarcheTitreGet[]; public_lecture: boolean; entreprises_lecture: boolean; titre_public_lecture: boolean } +type SuperDemarcheTitreGet = Omit<TitreGet['demarches'][0], 'etapes'> & { + etapes: SuperEtapeDemarcheTitreGet[] + public_lecture: boolean + entreprises_lecture: boolean + titre_public_lecture: boolean + machine_info: MachineInfo +} export const getTitre = async (pool: Pool, user: User, idOrSlug: TitreIdOrSlug): Promise<TitreGet | null> => { const titres = await dbQueryAndValidate(getTitreInternal, { id: idOrSlug }, pool, getTitreInternalValidator) @@ -67,7 +66,6 @@ export const getTitre = async (pool: Pool, user: User, idOrSlug: TitreIdOrSlug): return null } else { const titre = titres[0] - const titreDateLastModified = canSeeTitreLastModifiedDate(user) ? await callAndExit(getDateLastJournal(pool, titre.id)) : null const titreDoublon = titre.titre_doublon_id !== null && titre.titre_doublon_nom !== null ? { id: titre.titre_doublon_id, nom: titre.titre_doublon_nom } : null @@ -77,11 +75,17 @@ export const getTitre = async (pool: Pool, user: User, idOrSlug: TitreIdOrSlug): const superDemarches: SuperDemarcheTitreGet[] = [] for (const demarche of demarchesFromDatabase) { + const machineInfoResult = MachineInfo.withMachineId(titre.titre_type_id, demarche.demarche_type_id, demarche.id, demarche.machine_id) + if (!machineInfoResult.valid) { + throw new Error(machineInfoResult.error) + } + const machineInfo = machineInfoResult.value + const etapes = await callAndExit(getEtapesByDemarcheId(pool, demarche.id)) const formatedEtapes: SuperEtapeDemarcheTitreGet[] = [] for (const etape of etapes) { - const sections = getSections(titre.titre_type_id, demarche.demarche_type_id, etape.etape_type_id) + const sections = getSections(machineInfo, etape.etape_type_id) .map(section => ({ ...section, elements: section.elements.filter(element => !(etape.heritage_contenu?.[section.id]?.[element.id]?.actif ?? false)) })) .filter(section => section.elements.length > 0) @@ -89,7 +93,7 @@ export const getTitre = async (pool: Pool, user: User, idOrSlug: TitreIdOrSlug): const entrepriseDocuments = [] - const entrepriseDocumentsTypes = getEntrepriseDocuments(titre.titre_type_id, demarche.demarche_type_id, etape.etape_type_id) + const entrepriseDocumentsTypes = getEntrepriseDocuments(machineInfo, etape.etape_type_id) if (entrepriseDocumentsTypes.length > 0) { entrepriseDocuments.push(...(await callAndExit(getEntrepriseDocumentIdsByEtapeId({ titre_etape_id: etape.id }, pool, user)))) } @@ -205,6 +209,8 @@ export const getTitre = async (pool: Pool, user: User, idOrSlug: TitreIdOrSlug): id: demarche.id, slug: demarche.slug, description: demarche.description, + machine_id: demarche.machine_id, + machine_info: machineInfo, demarche_type_id: demarche.demarche_type_id, demarche_statut_id: demarche.demarche_statut_id, demarche_visibilite: demarche.public_lecture ? 'Publique' : 'Confidentielle', @@ -249,18 +255,7 @@ export const getTitre = async (pool: Pool, user: User, idOrSlug: TitreIdOrSlug): if (canRead) { const etape_documents: EtapeDocument[] = [] const isEtapeArmMecanise = isArmMecanise(superEtape.sections_with_values) - const firstEtapeDate = demarcheEnregistrementDemandeDateFind(superDemarche.etapes.map(({ etape_type_id, date }) => ({ date, typeId: etape_type_id }))) - - const firstEtapeDateOk = isNotNullNorUndefined(firstEtapeDate) ? firstEtapeDate : firstEtapeDateValidator.parse(superEtape.date) - const documentsTypes = getDocuments( - titre.titre_type_id, - superDemarche.demarche_type_id, - superEtape.etape_type_id, - firstEtapeDateOk, - superDemarche.id, - perimetre?.sdom_zones ?? [], - isEtapeArmMecanise - ) + const documentsTypes = getDocuments(superDemarche.machine_info, superEtape.etape_type_id, perimetre?.sdom_zones ?? [], isEtapeArmMecanise) if (isNotNullNorUndefinedNorEmpty(documentsTypes)) { etape_documents.push( ...(await callAndExit( @@ -271,15 +266,7 @@ export const getTitre = async (pool: Pool, user: User, idOrSlug: TitreIdOrSlug): const avis_documents: EtapeAvis[] = [] - const avisTypes = getAvisTypes( - superEtape.etape_type_id, - titre.titre_type_id, - superDemarche.demarche_type_id, - superDemarche.id, - firstEtapeDateOk, - perimetre?.communes.map(({ id }) => id) ?? [], - isEtapeArmMecanise - ) + const avisTypes = getAvisTypes(superEtape.etape_type_id, superDemarche.machine_info, perimetre?.communes.map(({ id }) => id) ?? [], isEtapeArmMecanise) if (isNotNullNorUndefinedNorEmpty(Object.keys(avisTypes))) { const avisWithLargeObjectId = await callAndExit( getEtapeAvisLargeObjectIdsByEtapeId(superEtape.id, pool, user, titreTypeId, administrationsLocales, entreprisesTitulairesOuAmodiataires, superEtape.etape_type_id, superDemarche) @@ -295,6 +282,7 @@ export const getTitre = async (pool: Pool, user: User, idOrSlug: TitreIdOrSlug): formattedDemarches.push({ id: superDemarche.id, slug: superDemarche.slug, + machine_id: superDemarche.machine_id, description: superDemarche.description, demarche_type_id: superDemarche.demarche_type_id, demarche_statut_id: superDemarche.demarche_statut_id, @@ -391,6 +379,7 @@ const getDemarchesByTitreIdQueryDbValidator = z.object({ entreprises_lecture: z.boolean().default(false), demarche_date_debut: caminoDateValidator.nullable(), demarche_date_fin: caminoDateValidator.nullable(), + machine_id: machineIdValidator.nullable(), ordre: z.number(), }) type GetDemarchesByTitreIdQueryDb = z.infer<typeof getDemarchesByTitreIdQueryDbValidator> @@ -409,6 +398,7 @@ select d.entreprises_lecture, d.demarche_date_debut, d.demarche_date_fin, + d.machine_id, d.ordre from titres_demarches d diff --git a/packages/api/src/api/rest/titres.queries.types.ts b/packages/api/src/api/rest/titres.queries.types.ts index 6852ce711..a28d40ace 100644 --- a/packages/api/src/api/rest/titres.queries.types.ts +++ b/packages/api/src/api/rest/titres.queries.types.ts @@ -40,6 +40,7 @@ export interface IGetDemarchesByTitreIdQueryDbResult { description: string | null; entreprises_lecture: boolean; id: string; + machine_id: string | null; ordre: number; public_lecture: boolean; slug: string | null; diff --git a/packages/api/src/api/rest/titres.test.integration.ts b/packages/api/src/api/rest/titres.test.integration.ts index d1193926a..54d19b96e 100644 --- a/packages/api/src/api/rest/titres.test.integration.ts +++ b/packages/api/src/api/rest/titres.test.integration.ts @@ -1,6 +1,5 @@ import { dbManager } from '../../../tests/db-manager' import { titreUpdate } from '../../database/queries/titres' -import { titreDemarcheCreate } from '../../database/queries/titres-demarches' import { titreEtapeCreate } from '../../database/queries/titres-etapes' import { userSuper } from '../../database/user-super' import { restCall, restDeleteCall, restNewCall, restNewPostCall } from '../../../tests/_utils/index' @@ -8,7 +7,7 @@ import { ADMINISTRATION_IDS } from 'camino-common/src/static/administrations' import { ITitreDemarche, ITitreEtape } from '../../types' import { entreprisesUpsert } from '../../database/queries/entreprises' import { Knex } from 'knex' -import { caminoDateValidator, toCaminoDate } from 'camino-common/src/date' +import { caminoDateValidator, firstEtapeDateValidator, toCaminoDate } from 'camino-common/src/date' import { afterAll, beforeAll, beforeEach, describe, test, expect, vi } from 'vitest' import { newEntrepriseId } from 'camino-common/src/entreprise' import type { Pool } from 'pg' @@ -27,6 +26,11 @@ import { testBlankUser } from 'camino-common/src/tests-utils' import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes' import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' import { ETAPES_STATUTS } from 'camino-common/src/static/etapesStatuts' +import { MachineInfo } from 'camino-common/src/machines' +import { TITRES_TYPES_IDS } from 'camino-common/src/static/titresTypes' +import { demarcheEnregistrementDemandeDateFind } from '../../business/rules-demarches/machines' +import { createDemarche } from './titre-demande.queries' +import { callAndExit } from '../../tools/fp-tools' console.info = vi.fn() console.error = vi.fn() @@ -118,7 +122,7 @@ afterAll(async () => { await dbManager.closeKnex() }) -const titreEtapesCreate = async (demarche: ITitreDemarche, etapes: Omit<ITitreEtape, 'id' | 'titreDemarcheId' | 'concurrence' | 'hasTitreFrom'>[]) => { +const titreEtapesCreate = async (demarche: Pick<ITitreDemarche, 'id' | 'titreId'>, etapes: Omit<ITitreEtape, 'id' | 'titreDemarcheId' | 'concurrence' | 'hasTitreFrom'>[]) => { const etapesCrees = [] for (const etape of etapes) { etapesCrees.push( @@ -142,10 +146,12 @@ async function createTitreWithEtapes( entreprises: any ) { const titreId = newTitreId(`id-${nomTitre}`) + const titreTypeId = TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX + const demarcheTypeId = DEMARCHES_TYPES_IDS.Octroi await insertTitreGraph({ id: titreId, nom: nomTitre, - typeId: 'arm', + typeId: titreTypeId, titreStatutId: 'mod', propsTitreEtapesIds: {}, references: [ @@ -156,18 +162,18 @@ async function createTitreWithEtapes( ], }) - const titreDemarche = await titreDemarcheCreate({ - titreId, - typeId: 'oct', - }) + const titreDemarcheId = await callAndExit(createDemarche(dbPool, titreId, titreTypeId, demarcheTypeId)) const [firstEtape, ...remainingEtapes] = etapes - const etapesCrees = await titreEtapesCreate(titreDemarche, [ + const etapesCrees = await titreEtapesCreate({ id: titreDemarcheId, titreId }, [ { demarcheIdsConsentement: [], ...firstEtape, titulaireIds: [entreprises[0].id] }, ...remainingEtapes.map(e => ({ demarcheIdsConsentement: [], ...e })), ]) + const firstEtapeDate = demarcheEnregistrementDemandeDateFind(etapes) + await knex('titres_demarches').update({ machineId: MachineInfo.withDate(titreTypeId, demarcheTypeId, titreDemarcheId, firstEtapeDate ?? firstEtapeDateValidator.parse(firstEtape.date)).machineId }) + await knex('titres') .update({ propsTitreEtapesIds: { titulaires: etapesCrees[0].id, points: etapesCrees[0].id } }) .where('id', titreId) @@ -590,6 +596,7 @@ describe('getTitre', () => { }, ], "id": "demarche-id", + "machine_id": null, "ordre": 0, "slug": "titre-id-oct99", }, @@ -690,6 +697,7 @@ describe('titresSuper', () => { demarches: [ { id: demarcheId, + machineId: null, typeId: DEMARCHES_TYPES_IDS.Octroi, titreId: id, etapes: [ @@ -716,6 +724,7 @@ describe('titresSuper', () => { demarches: [ { id: demarcheIdSansBrouillon, + machineId: null, typeId: DEMARCHES_TYPES_IDS.Octroi, titreId: idSansBrouillon, etapes: [ @@ -741,6 +750,7 @@ describe('titresSuper', () => { "etape_date": "2025-01-10", "etape_slug": "demarcheIdAvecBrouillon-mfr99", "etape_type_id": "mfr", + "machine_id": null, "titre_nom": "mon titre avec brouillon", "titre_slug": "slug", "titre_statut_id": "val", diff --git a/packages/api/src/api/rest/titres.ts b/packages/api/src/api/rest/titres.ts index c44b988e0..991507781 100644 --- a/packages/api/src/api/rest/titres.ts +++ b/packages/api/src/api/rest/titres.ts @@ -27,11 +27,11 @@ import { RestNewGetCall, RestNewPostCall } from '../../server/rest' import { Effect, Match, pipe } from 'effect' import { CaminoError } from 'camino-common/src/zod-tools' import { EffectDbQueryAndValidateErrors } from '../../pg-database' -import { CaminoMachines, machineFind } from '../../business/rules-demarches/machines' -import { demarcheEnregistrementDemandeDateFind } from 'camino-common/src/demarche' import { DBTitre } from '../../database/models/titres' import { AdministrationId } from 'camino-common/src/static/administrations' import { filterOrFailFromValid } from '../../tools/fp-tools' +import { ApiMachineInfo } from '../../business/rules-demarches/machines' +import { MachineInfo } from 'camino-common/src/machines' const etapesAMasquer = [ETAPES_TYPES.classementSansSuite, ETAPES_TYPES.desistementDuDemandeur, ETAPES_TYPES.demandeDeComplements_RecevabiliteDeLaDemande_] @@ -148,21 +148,21 @@ export const titresAdministrations = if (demarcheLaPlusRecente.statutId !== DemarchesStatutsIds.EnConstruction) { const etapes = demarcheLaPlusRecente.etapes.map(etape => titreEtapeForMachineValidator.parse(etape)) const etapesDerniereDemarche = toMachineEtapes(etapes) - const firstEtapeDate = demarcheEnregistrementDemandeDateFind(demarcheLaPlusRecente.etapes) - let machine: CaminoMachines | undefined - // TODO 2024-12-02 à virer quand on enlève deepreadonly et qu'on type mieux demarcheEnregistrementDemandeDateFind - if (isNotNullNorUndefined(firstEtapeDate)) { - machine = machineFind(titre.typeId, demarcheLaPlusRecente.typeId, demarcheLaPlusRecente.id, firstEtapeDate) + const machineInfo = MachineInfo.withMachineId(titre.typeId, demarcheLaPlusRecente.typeId, demarcheLaPlusRecente.id, demarcheLaPlusRecente.machineId) + if (!machineInfo.valid) { + throw new Error(`La machine associée à la démarche est incohérente : ${machineInfo.error}`) } + + const machine = new ApiMachineInfo(machineInfo.value) derniereEtape = etapesDerniereDemarche[etapesDerniereDemarche.length - 1] - if (isNotNullNorUndefined(machine)) { + if (isNotNullNorUndefined(machine.machine)) { try { - const whoIsBlocking = machine.whoIsBlocking(etapesDerniereDemarche) + const whoIsBlocking = machine.machine.whoIsBlocking(etapesDerniereDemarche) if (!whoIsBlocking.valid) { throw new Error(whoIsBlocking.error) } enAttenteDeAdministration = whoIsBlocking.value.includes(user.administrationId) - const nextEtapes = machine.possibleNextEtapes(etapesDerniereDemarche, getCurrent()) + const nextEtapes = machine.machine.possibleNextEtapes(etapesDerniereDemarche, getCurrent()) if (!nextEtapes.valid) { throw new Error(nextEtapes.error) } diff --git a/packages/api/src/business/check-prolongations.ts b/packages/api/src/business/check-prolongations.ts index 370e61b2d..7e69109c5 100644 --- a/packages/api/src/business/check-prolongations.ts +++ b/packages/api/src/business/check-prolongations.ts @@ -24,6 +24,7 @@ import { isDemarcheTypeProlongations } from 'camino-common/src/static/demarchesT import { getMostRecentValuePropFromEtapeFondamentaleValide, TitreGetDemarche } from 'camino-common/src/titres' import { isDemarcheStatutNonStatue, isDemarcheStatutNonValide } from 'camino-common/src/static/demarchesStatuts' import { getTitre } from '../api/rest/titres.queries' +import { MachineInfo } from 'camino-common/src/machines' type CheckedProlongation = { titre_slug: TitreSlug | null @@ -102,7 +103,6 @@ const checkOneProlongation = (pool: Pool, demarcheId: DemarcheId): Effect.Effect } ) ), - Effect.bind('flattenFirstEtape', ({ firstEtape }) => iTitreEtapeToFlattenEtape(firstEtape)), Effect.bind('firstEtapeDate', ({ demarche }) => getFirstEtapeDateByDemarcheIdOrSlug(demarche.demarche_id, pool).pipe( Effect.filterOrFail( @@ -111,19 +111,18 @@ const checkOneProlongation = (pool: Pool, demarcheId: DemarcheId): Effect.Effect ) ) ), - Effect.map(({ demarche, firstEtape, flattenFirstEtape, etapeDocuments, entrepriseDocuments, etapeAvis, firstEtapeDate }) => { + Effect.let('machineInfo', ({ demarche, firstEtapeDate }) => MachineInfo.withDate(demarche.titre_type_id, demarche.demarche_type_id, demarcheId, firstEtapeDate)), + Effect.bind('flattenFirstEtape', ({ firstEtape, machineInfo }) => iTitreEtapeToFlattenEtape(machineInfo, firstEtape)), + Effect.map(({ demarche, firstEtape, flattenFirstEtape, etapeDocuments, entrepriseDocuments, etapeAvis, machineInfo }) => { const isFirstEtapeComplete = isEtapeComplete( flattenFirstEtape, - demarche.titre_type_id, - demarcheId, - demarche.demarche_type_id, + machineInfo, etapeDocuments, entrepriseDocuments, firstEtape.sdomZones, isNotNullNorUndefined(firstEtape.communes) ? firstEtape.communes.map(({ id }) => id) : [], etapeAvis, - userSuper, - firstEtapeDate + userSuper ) return { diff --git a/packages/api/src/business/daily.ts b/packages/api/src/business/daily.ts index d659a33cb..7ba3e8a6b 100644 --- a/packages/api/src/business/daily.ts +++ b/packages/api/src/business/daily.ts @@ -31,6 +31,7 @@ import { createInterface } from 'node:readline' import { fetch } from 'undici' import { mailjetSend } from '../tools/api-mailjet/emails' import { EtapeId } from 'camino-common/src/etape' +import { demarcheMachineIdsUpdate } from './processes/demarche-machine-id-update' interface Daily { heritageWithUnknownEtapes: unknown[] @@ -47,6 +48,7 @@ interface Daily { updated: EtapeId[] errors: EtapeId[] } + demarcheMachineIdsUpdated: unknown[] titresDemarchesStatutUpdated: string[] titresDemarchesPublicUpdated: string[] titresDemarchesOrdreUpdated: string[] @@ -62,8 +64,8 @@ interface Daily { titresUpdatedIndex: TitreSlugUpdate[] } -// Mis à jour le 2025-03-12 -const NOMBRE_ERREURS_ETAPES = 9964 as const +// Mis à jour le 2025-04-07 +const NOMBRE_ERREURS_ETAPES = 9927 as const type DailyResult = { changes: false } | { changes: true; logs: NonEmptyArray<string> } const dailyResult = (daily: Daily | null): DailyResult => { @@ -129,6 +131,10 @@ const dailyResult = (daily: Daily | null): DailyResult => { logs.push(`erreurs: ${daily.titresEtapesHeritageContenuUpdated.errors.length} étape(s) (héritage du contenu) en erreur`) } + if (isNotNullNorUndefinedNorEmpty(daily.demarcheMachineIdsUpdated)) { + logs.push(`mise à jour: ${daily.demarcheMachineIdsUpdated.length} machines`) + } + if (isNotNullNorUndefinedNorEmpty(daily.titresDemarchesStatutUpdated)) { logs.push(`mise à jour: ${daily.titresDemarchesStatutUpdated.length} démarche(s) (statut)`) } @@ -239,6 +245,7 @@ const rawDaily = async (pool: Pool): Promise<DailyResult> => { const titresEtapesHeritageContenuUpdated = await titresEtapesHeritageContenuUpdate(pool, userSuper) const heritageWithUnknownEtapes = await callAndExit(checkEtapeInContenuHeritage(pool)) + const demarcheMachineIdsUpdated = await callAndExit(demarcheMachineIdsUpdate(pool)) const titresDemarchesStatutUpdated = await titresDemarchesStatutIdUpdate(pool) const titresDemarchesOrdreUpdated = await titresDemarchesOrdreUpdate() const titresDemarchesDatesUpdated = await titresDemarchesDatesUpdate(pool) @@ -260,6 +267,7 @@ const rawDaily = async (pool: Pool): Promise<DailyResult> => { const etapesCompletesErreurs = await etapesCompletesCheck(pool) return dailyResult({ + demarcheMachineIdsUpdated, heritageWithUnknownEtapes, etapesCompletesErreurs: etapesCompletesErreurs, tdeErreurs, diff --git a/packages/api/src/business/fill-documents-non-renseigne.ts b/packages/api/src/business/fill-documents-non-renseigne.ts index 732212760..2ecfa7f0d 100644 --- a/packages/api/src/business/fill-documents-non-renseigne.ts +++ b/packages/api/src/business/fill-documents-non-renseigne.ts @@ -1,7 +1,7 @@ import { Pool } from 'pg' import { Effect, pipe } from 'effect' import { CaminoError } from 'camino-common/src/zod-tools' -import { demarcheEnregistrementDemandeDateFind, DemarcheEtapeFondamentale, DemarcheId } from 'camino-common/src/demarche' +import { DemarcheEtapeFondamentale, DemarcheId } from 'camino-common/src/demarche' import { isEtapeComplete } from 'camino-common/src/permissions/titres-etapes' import { userSuper } from '../database/user-super' import { FirstEtapeDate } from 'camino-common/src/date' @@ -28,6 +28,8 @@ import { getMostRecentValuePropFromEtapeFondamentaleValide, TitreGetDemarche } f import { isDemarcheStatutNonStatue, isDemarcheStatutNonValide } from 'camino-common/src/static/demarchesStatuts' import { getAvisTypes } from 'camino-common/src/avisTypes' import { AvisRegularTypeId, isAvisRegularTypeId } from 'camino-common/src/static/avisTypes' +import { MachineInfo } from 'camino-common/src/machines' +import { demarcheEnregistrementDemandeDateFind } from './rules-demarches/machines' type CheckedProlongation = { titre_slug: TitreSlug @@ -158,7 +160,15 @@ const checkDemarcheEtapes = (pool: Pool, titreId: TitreId): Effect.Effect<Checke } ) ), - Effect.bind('flattenEtape', ({ etapeFull }) => iTitreEtapeToFlattenEtape(etapeFull)), + Effect.bind('machineInfo', () => { + const machineInfo = MachineInfo.withMachineId(titre.titre_type_id, demarche.demarche_type_id, demarche.id, demarche.machine_id) + if (!machineInfo.valid) { + return Effect.fail({ message: 'Machine associée à la démarche incohérente', extra: machineInfo.error }) + } + + return Effect.succeed(machineInfo.value) + }), + Effect.bind('flattenEtape', ({ etapeFull, machineInfo }) => iTitreEtapeToFlattenEtape(machineInfo, etapeFull)), Effect.map(({ etapeFull, flattenEtape, etapeDocuments, entrepriseDocuments, etapeAvis }) => { if (flattenEtape.isBrouillon === ETAPE_IS_BROUILLON) { @@ -166,16 +176,13 @@ const checkDemarcheEtapes = (pool: Pool, titreId: TitreId): Effect.Effect<Checke } const isFirstEtapeComplete = isEtapeComplete( flattenEtape, - titre.titre_type_id, - demarche.id, - demarche.demarche_type_id, + MachineInfo.withDate(titre.titre_type_id, demarche.demarche_type_id, demarche.id, firstEtapeDate), etapeDocuments, entrepriseDocuments, etapeFull.sdomZones, isNotNullNorUndefined(etapeFull.communes) ? etapeFull.communes.map(({ id }) => id) : [], etapeAvis, - userSuper, - firstEtapeDate + userSuper ) const result: CheckedProlongation = { titre_slug: titre.slug, @@ -237,11 +244,8 @@ const addDocumentNonRenseigne = (pool: Pool, checkedProlongation: CheckedProlong ), Effect.flatMap(({ titre, demarche }) => { const documentTypes = getDocuments( - titre.titre_type_id, - demarche.demarche_type_id, + MachineInfo.withDate(titre.titre_type_id, demarche.demarche_type_id, demarche.id, checkedProlongation.firstEtapeDate), checkedProlongation.etapeFull.typeId, - checkedProlongation.firstEtapeDate, - demarche.id, checkedProlongation.etapeFull.sdomZones ?? [], isArmMecanise(checkedProlongation.flattenEtape.contenu) ) @@ -298,10 +302,7 @@ const addAvisNonRenseigne = (pool: Pool, checkedProlongation: CheckedProlongatio Effect.flatMap(({ titre, demarche }) => { const avisTypes = getAvisTypes( checkedProlongation.etapeFull.typeId, - titre.titre_type_id, - demarche.demarche_type_id, - demarche.id, - checkedProlongation.firstEtapeDate, + MachineInfo.withDate(titre.titre_type_id, demarche.demarche_type_id, demarche.id, checkedProlongation.firstEtapeDate), (checkedProlongation.propsHeritees.perimetre?.communes ?? []).map(({ id }) => id), isArmMecanise(checkedProlongation.flattenEtape.contenu) ) diff --git a/packages/api/src/business/processes/demarche-machine-id-update.ts b/packages/api/src/business/processes/demarche-machine-id-update.ts new file mode 100644 index 000000000..6f612b574 --- /dev/null +++ b/packages/api/src/business/processes/demarche-machine-id-update.ts @@ -0,0 +1,51 @@ +import { CaminoMachineId } from 'camino-common/src/validators/machine' +import { CaminoError } from 'camino-common/src/zod-tools' +import { Effect } from 'effect' +import { Pool } from 'pg' +import { DemarcheId, DemarcheSlug } from 'camino-common/src/demarche' +import { getDemarcheByIdOrSlug, GetDemarcheByIdOrSlugErrors, getDemarches, getFirstEtapeDateByDemarcheIdOrSlug, GetFirstEtapeDateByDemarcheIdOrSlugErrors } from '../../api/rest/demarches.queries' +import { MachineInfo } from 'camino-common/src/machines' +import { isNotNullNorUndefined } from 'camino-common/src/typescript-tools' +import { updateMachineId, UpdateMachineIdErrors } from './update-machine-id.queries' + +export const demarcheMachineIdsUpdate = (pool: Pool): Effect.Effect<Changes[], CaminoError<DemarcheMachineIdUpdateErrors>> => { + console.info('') + console.info('machine des démarches…') + return Effect.Do.pipe( + Effect.flatMap(() => getDemarches(pool)), + Effect.flatMap(demarches => Effect.forEach(demarches, demarche => demarcheMachineIdUpdate(pool, demarche.id))), + Effect.map(changesAndNoChanges => changesAndNoChanges.filter(value => value.changes)) + ) +} + +type Changes = { changes: true; demarcheSlug: DemarcheSlug; old: CaminoMachineId | null; new: CaminoMachineId | null } +type NoChange = { changes: false } +type ReturnValue = Changes | NoChange +type DemarcheMachineIdUpdateErrors = GetFirstEtapeDateByDemarcheIdOrSlugErrors | GetDemarcheByIdOrSlugErrors | UpdateMachineIdErrors +export const demarcheMachineIdUpdate = (pool: Pool, demarcheId: DemarcheId): Effect.Effect<ReturnValue, CaminoError<DemarcheMachineIdUpdateErrors>> => { + return Effect.Do.pipe( + Effect.bind('demarche', () => getDemarcheByIdOrSlug(pool, demarcheId)), + Effect.bind('firstEtapeDate', () => getFirstEtapeDateByDemarcheIdOrSlug(demarcheId, pool)), + Effect.let('newMachineId', ({ demarche, firstEtapeDate }) => + isNotNullNorUndefined(firstEtapeDate) ? (MachineInfo.withDate(demarche.titre_type_id, demarche.demarche_type_id, demarche.demarche_id, firstEtapeDate).machineId ?? null) : null + ), + Effect.flatMap(({ demarche, newMachineId }) => { + if (demarche.machine_id === newMachineId) { + return Effect.succeed<ReturnValue>({ changes: false }) + } + + return Effect.Do.pipe( + Effect.flatMap(() => updateMachineId(pool, demarcheId, newMachineId)), + Effect.map(() => { + console.info(`Changement de machine pour la démarche https://camino.beta.gouv.fr/demarches/${demarche.demarche_slug} old: ${demarche.machine_id} -> ${newMachineId}`) + return { + changes: true, + demarcheSlug: demarche.demarche_slug, + old: demarche.machine_id, + new: newMachineId, + } + }) + ) + }) + ) +} diff --git a/packages/api/src/business/processes/titres-demarches-public-update.ts b/packages/api/src/business/processes/titres-demarches-public-update.ts index a4fbcdd5e..fe50f37b9 100644 --- a/packages/api/src/business/processes/titres-demarches-public-update.ts +++ b/packages/api/src/business/processes/titres-demarches-public-update.ts @@ -3,6 +3,7 @@ import { titreDemarchePublicFind } from '../rules/titre-demarche-public-find' import { titresGet } from '../../database/queries/titres' import { userSuper } from '../../database/user-super' import { DemarcheId } from 'camino-common/src/demarche' +import { MachineInfo } from 'camino-common/src/machines' type ITitreDemarchePatch = { publicLecture: boolean @@ -33,7 +34,12 @@ export const titresDemarchesPublicUpdate = async (titresIds?: string[]): Promise for (const titre of titres) { for (const titreDemarche of titre.demarches!) { - const { publicLecture, entreprisesLecture } = titreDemarchePublicFind(titreDemarche, titre.typeId) + const machineInfo = MachineInfo.withMachineId(titre.typeId, titreDemarche.typeId, titreDemarche.id, titreDemarche.machineId) + if (!machineInfo.valid) { + throw new Error(`La machine associée à la démarche est incohérente: ${machineInfo.error}`) + } + + const { publicLecture, entreprisesLecture } = titreDemarchePublicFind(machineInfo.value, titreDemarche) const patch = {} as ITitreDemarchePatch diff --git a/packages/api/src/business/processes/titres-demarches-statut-ids-update.test.ts b/packages/api/src/business/processes/titres-demarches-statut-ids-update.test.ts index b36f7ce18..dd571b91f 100644 --- a/packages/api/src/business/processes/titres-demarches-statut-ids-update.test.ts +++ b/packages/api/src/business/processes/titres-demarches-statut-ids-update.test.ts @@ -25,6 +25,7 @@ describe("statut des démarches d'un titre", () => { getDemarchesMock.mockReturnValue( Effect.succeed({ [newDemarcheId('')]: { + machineId: null, id: newDemarcheId('h-cx-courdemanges-1988-oct01'), slug: demarcheSlugValidator.parse('h-cx-courdemanges-1988-oct01'), titreId: newTitreId('h-cx-courdemanges-1988'), @@ -82,6 +83,7 @@ describe("statut des démarches d'un titre", () => { getDemarchesMock.mockReturnValue( Effect.succeed({ [newDemarcheId('')]: { + machineId: null, id: newDemarcheId('h-cx-courdemanges-1988-oct01'), slug: demarcheSlugValidator.parse('h-cx-courdemanges-1988-oct01'), titreId: newTitreId('h-cx-courdemanges-1988'), @@ -138,6 +140,7 @@ describe("statut des démarches d'un titre", () => { getDemarchesMock.mockReturnValue( Effect.succeed({ [newDemarcheId('')]: { + machineId: null, id: newDemarcheId('h-cx-courdemanges-1988-oct01'), slug: demarcheSlugValidator.parse('h-cx-courdemanges-1988-oct01'), titreId: newTitreId('h-cx-courdemanges-1988'), diff --git a/packages/api/src/business/processes/titres-demarches-statut-ids-update.ts b/packages/api/src/business/processes/titres-demarches-statut-ids-update.ts index 572123625..4d9e7e04f 100644 --- a/packages/api/src/business/processes/titres-demarches-statut-ids-update.ts +++ b/packages/api/src/business/processes/titres-demarches-statut-ids-update.ts @@ -5,6 +5,7 @@ import { titreEtapesSortAscByOrdre } from '../utils/titre-etapes-sort' import { getDemarches } from './titres-etapes-heritage-contenu-update.queries' import { Pool } from 'pg' import { callAndExit } from '../../tools/fp-tools' +import { MachineInfo } from 'camino-common/src/machines' export const titresDemarchesStatutIdUpdate = async (pool: Pool, titreId?: TitreId): Promise<string[]> => { console.info() @@ -17,7 +18,12 @@ export const titresDemarchesStatutIdUpdate = async (pool: Pool, titreId?: TitreI for (const titreDemarche of Object.values(titresDemarches)) { const titreDemarcheEtapes = titreEtapesSortAscByOrdre(titreDemarche.etapes) - const statutId = titreDemarcheStatutIdFind(titreDemarche.typeId, titreDemarcheEtapes, titreDemarche.titreTypeId, titreDemarche.id) + const machineInfo = MachineInfo.withMachineId(titreDemarche.titreTypeId, titreDemarche.typeId, titreDemarche.id, titreDemarche.machineId) + if (!machineInfo.valid) { + throw new Error(`La machine associée à la démarche est incohérente: ${machineInfo.error}`) + } + + const statutId = titreDemarcheStatutIdFind(machineInfo.value, titreDemarcheEtapes) if (titreDemarche.statutId !== statutId) { await titreDemarcheUpdate(titreDemarche.id, { statutId }) diff --git a/packages/api/src/business/processes/titres-etapes-consentement.test.integration.ts b/packages/api/src/business/processes/titres-etapes-consentement.test.integration.ts index 85475834d..4e004485a 100644 --- a/packages/api/src/business/processes/titres-etapes-consentement.test.integration.ts +++ b/packages/api/src/business/processes/titres-etapes-consentement.test.integration.ts @@ -54,7 +54,7 @@ describe('etapeConsentementUpdate', () => { } test("ne fait rien si le périmètre de l'étape est null", async () => { - const { etapeId } = await createTitreWithDemarcheAndEtape(titre, { typeId: DEMARCHES_TYPES_IDS.Octroi }, etape) + const { etapeId } = await createTitreWithDemarcheAndEtape(titre, { machineId: null, typeId: DEMARCHES_TYPES_IDS.Octroi }, etape) await expect(callAndExit(etapeConsentementUpdate(dbPool, etapeId))).resolves.toBe(null) }) @@ -86,7 +86,7 @@ describe('etapeConsentementUpdate', () => { const perimetre = featureMultipolygon(index++) const { demarcheId: demarcheIdConsentement } = await createTitreWithDemarcheAndEtape( titre, - { typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: demarcheConsentementDateDebut }, + { machineId: null, typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: demarcheConsentementDateDebut }, { ...etape, geojson4326Perimetre: perimetre, @@ -98,7 +98,7 @@ describe('etapeConsentementUpdate', () => { const { etapeId } = await createTitreWithDemarcheAndEtape( titre, - { typeId: DEMARCHES_TYPES_IDS.Octroi }, + { machineId: null, typeId: DEMARCHES_TYPES_IDS.Octroi }, { ...etape, date: dateDemande, @@ -124,7 +124,7 @@ describe('etapeConsentementUpdate', () => { const perimetre = featureMultipolygon(index++) await createTitreWithDemarcheAndEtape( titre, - { typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: demarcheConsentementDateDebut }, + { machineId: null, typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: demarcheConsentementDateDebut }, { ...etape, geojson4326Perimetre: perimetre, @@ -135,7 +135,7 @@ describe('etapeConsentementUpdate', () => { const { etapeId } = await createTitreWithDemarcheAndEtape( titre, - { typeId: DEMARCHES_TYPES_IDS.Octroi }, + { machineId: null, typeId: DEMARCHES_TYPES_IDS.Octroi }, { ...etape, date: dateDemande, @@ -152,7 +152,7 @@ describe('etapeConsentementUpdate', () => { const perimetre1 = featureMultipolygon(index++) await createTitreWithDemarcheAndEtape( titre, - { typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: demarcheConsentementDateDebut }, + { machineId: null, typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: demarcheConsentementDateDebut }, { ...etape, geojson4326Perimetre: perimetre1, @@ -165,7 +165,7 @@ describe('etapeConsentementUpdate', () => { const perimetre2 = featureMultipolygon(index++) const { etapeId } = await createTitreWithDemarcheAndEtape( titre, - { typeId: DEMARCHES_TYPES_IDS.Octroi }, + { machineId: null, typeId: DEMARCHES_TYPES_IDS.Octroi }, { ...etape, date: dateDemande, @@ -185,7 +185,7 @@ describe('etapeConsentementUpdate', () => { //Se termine avant la demande await createTitreWithDemarcheAndEtape( titre, - { typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: demarcheConsentementDateDebut, demarcheDateFin: dateAddDays(demarcheConsentementDateDebut, 1) }, + { machineId: null, typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: demarcheConsentementDateDebut, demarcheDateFin: dateAddDays(demarcheConsentementDateDebut, 1) }, { ...etape, geojson4326Perimetre: perimetre1, @@ -198,7 +198,7 @@ describe('etapeConsentementUpdate', () => { //Commence après la demande await createTitreWithDemarcheAndEtape( titre, - { typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: dateAddDays(dateDemande, 10) }, + { machineId: null, typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: dateAddDays(dateDemande, 10) }, { ...etape, geojson4326Perimetre: perimetre1, @@ -211,7 +211,7 @@ describe('etapeConsentementUpdate', () => { const perimetre2 = featureMultipolygon(index++) const { etapeId } = await createTitreWithDemarcheAndEtape( titre, - { typeId: DEMARCHES_TYPES_IDS.Octroi }, + { machineId: null, typeId: DEMARCHES_TYPES_IDS.Octroi }, { ...etape, date: dateDemande, diff --git a/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.queries.ts b/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.queries.ts index 1a9e02c29..12f49df34 100644 --- a/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.queries.ts +++ b/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.queries.ts @@ -18,6 +18,7 @@ import { isNotNullNorUndefined } from 'camino-common/src/typescript-tools' import { km2Validator } from 'camino-common/src/number' import { CaminoError } from 'camino-common/src/zod-tools' import { Effect } from 'effect' +import { CaminoMachineId, machineIdValidator } from 'camino-common/src/validators/machine' const getAllEtapeIdValidator = z.object({ id: etapeIdValidator, heritage_contenu: z.record(z.record(z.object({ etapeId: etapeIdValidator.optional().nullable() }))).nullable() }) @@ -56,6 +57,7 @@ const getEtapesByDemarcheValidator = z.object({ is_brouillon: etapeBrouillonValidator.nullable(), has_titre_from: z.boolean(), demarche_ids_consentement: z.array(demarcheIdValidator).nullable(), + machine_id: machineIdValidator.nullable(), }) export const getDemarches = ( @@ -72,6 +74,7 @@ export const getDemarches = ( titreTypeId: TitreTypeId titreId: TitreId statutId: DemarcheStatutId + machineId: CaminoMachineId | null } }, CaminoError<EffectDbQueryAndValidateErrors> @@ -88,6 +91,7 @@ export const getDemarches = ( titreTypeId: TitreTypeId titreId: TitreId statutId: DemarcheStatutId + machineId: CaminoMachineId | null } }>((acc, row) => { if (!isNotNullNorUndefined(acc[row.demarche_id])) { @@ -99,6 +103,7 @@ export const getDemarches = ( titreTypeId: row.titre_type_id, typeId: row.demarche_type_id, statutId: row.demarche_statut_id, + machineId: row.machine_id, } } if ( @@ -161,6 +166,7 @@ SELECT demarche.slug as demarche_slug, demarche.type_id as demarche_type_id, demarche.statut_id as demarche_statut_id, + demarche.machine_id, etape.communes AS communes, demarche_concurrente.public_lecture as demarche_concurrente_public_lecture, EXISTS(select 1 from titres__titres tt where titre.id = tt.titre_to_id) as has_titre_from diff --git a/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.queries.types.ts b/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.queries.types.ts index dc9a60226..d800c3f30 100644 --- a/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.queries.types.ts +++ b/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.queries.types.ts @@ -41,6 +41,7 @@ export interface IGetEtapesByDemarcheInternalResult { heritage_contenu: Json | null; id: string; is_brouillon: boolean; + machine_id: string | null; ordre: number; statut_id: string; surface: number | null; diff --git a/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.ts b/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.ts index 71a1d2033..f04286802 100644 --- a/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.ts +++ b/packages/api/src/business/processes/titres-etapes-heritage-contenu-update.ts @@ -12,6 +12,7 @@ import { callAndExit } from '../../tools/fp-tools' import { Effect } from 'effect' import { CaminoError } from 'camino-common/src/zod-tools' import { EffectDbQueryAndValidateErrors } from '../../pg-database' +import { MachineInfo } from 'camino-common/src/machines' function isEmpty(obj: any) { for (const prop in obj) { if (Object.prototype.hasOwnProperty.call(obj, prop)) { @@ -69,11 +70,16 @@ export const titresEtapesHeritageContenuUpdate = async (pool: Pool, user: UserNo const titresEtapesIdsErrors: EtapeId[] = [] for (const titreDemarche of Object.values(titresDemarches)) { + const machineInfo = MachineInfo.withMachineId(titreDemarche.titreTypeId, titreDemarche.typeId, titreDemarche.id, titreDemarche.machineId) + if (!machineInfo.valid) { + throw new Error(`La machine associée à la démarche est incohérente: ${machineInfo.error}`) + } + if (isNotNullNorUndefinedNorEmpty(titreDemarche.etapes)) { const etapeSectionsDictionary = titreDemarche.etapes.reduce<{ [etapeId in EtapeId]?: Section[] }>((acc, e) => { - acc[e.id] = getSections(titreDemarche.titreTypeId, titreDemarche.typeId, e.typeId) + acc[e.id] = getSections(machineInfo.value, e.typeId) return acc }, {}) diff --git a/packages/api/src/business/processes/titres-etapes-mise-en-concurrence.test.integration.ts b/packages/api/src/business/processes/titres-etapes-mise-en-concurrence.test.integration.ts index 326e2bc89..ac2cdae0b 100644 --- a/packages/api/src/business/processes/titres-etapes-mise-en-concurrence.test.integration.ts +++ b/packages/api/src/business/processes/titres-etapes-mise-en-concurrence.test.integration.ts @@ -80,6 +80,7 @@ const createTitreWithDemarcheAndEtape = async (titreTypeId: TitreTypeId, demarch typeId: titreTypeId, demarches: [ { + machineId: null, id: demarcheId, titreId, typeId: demarcheTypeId, @@ -152,6 +153,7 @@ describe('etapeMiseEnConcurrenceUpdate', () => { typeId: TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, demarches: [ { + machineId: null, id: demarcheId, titreId, typeId: DEMARCHES_TYPES_IDS.Octroi, @@ -187,6 +189,7 @@ describe('etapeMiseEnConcurrenceUpdate', () => { typeId: TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, demarches: [ { + machineId: null, id: demarcheId2, titreId: titreId2, typeId: DEMARCHES_TYPES_IDS.Octroi, @@ -232,6 +235,7 @@ describe('etapeMiseEnConcurrenceUpdate', () => { typeId: TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, demarches: [ { + machineId: null, id: demarcheId, titreId, typeId: DEMARCHES_TYPES_IDS.Octroi, @@ -259,6 +263,7 @@ describe('etapeMiseEnConcurrenceUpdate', () => { typeId: TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, demarches: [ { + machineId: null, id: demarcheId2, titreId: titreId2, typeId: DEMARCHES_TYPES_IDS.Octroi, diff --git a/packages/api/src/business/processes/titres-etapes-ordre-update.test.ts b/packages/api/src/business/processes/titres-etapes-ordre-update.test.ts index da4a78e5b..02e24dc1a 100644 --- a/packages/api/src/business/processes/titres-etapes-ordre-update.test.ts +++ b/packages/api/src/business/processes/titres-etapes-ordre-update.test.ts @@ -6,12 +6,14 @@ import { vi, afterEach, describe, expect, test } from 'vitest' import { newDemarcheId, newEtapeId } from '../../database/models/_format/id-create' import { caminoDateValidator } from 'camino-common/src/date' import { DemarcheId } from 'camino-common/src/demarche' -import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' -import { TitreTypeId } from 'camino-common/src/static/titresTypes' +import { DEMARCHES_TYPES_IDS, DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' +import { TITRES_TYPES_IDS, TitreTypeId } from 'camino-common/src/static/titresTypes' import { TitreId, titreIdValidator } from 'camino-common/src/validators/titres' import { TitreEtapeForMachine } from '../rules-demarches/machine-common' import { ETAPE_IS_NOT_BROUILLON } from 'camino-common/src/etape' import { ZERO_KM2 } from 'camino-common/src/number' +import { CaminoMachineId } from 'camino-common/src/validators/machine' +import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' vi.mock('../../database/queries/titres-etapes', () => ({ titreEtapeUpdate: vi.fn().mockResolvedValue(true), })) @@ -24,12 +26,14 @@ const titresDemarchesEtapes: { typeId: DemarcheTypeId titreTypeId: TitreTypeId titreId: TitreId + machineId: CaminoMachineId | null } } = { [demarcheId]: { id: demarcheId, - typeId: 'amo', - titreTypeId: 'apc', + machineId: 'ProcedureSimplifiee', + typeId: DEMARCHES_TYPES_IDS.Amodiation, + titreTypeId: TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_CARRIERES, titreId: titreIdValidator.parse('titreId'), etapes: [ { @@ -39,7 +43,7 @@ const titresDemarchesEtapes: { dateFin: null, dateDebut: null, duree: null, - typeId: 'asc', + typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', statutId: 'fai', @@ -55,7 +59,7 @@ const titresDemarchesEtapes: { dateFin: null, dateDebut: null, duree: null, - typeId: 'asc', + typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, statutId: 'fai', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -75,9 +79,17 @@ const titresDemarchesEtapesVides: { typeId: DemarcheTypeId titreTypeId: TitreTypeId titreId: TitreId + machineId: CaminoMachineId | null } } = { - [demarcheId]: { id: demarcheId, typeId: 'amo', titreTypeId: 'apc', titreId: titreIdValidator.parse('titreId'), etapes: [] }, + [demarcheId]: { + id: demarcheId, + machineId: null, + typeId: DEMARCHES_TYPES_IDS.Amodiation, + titreTypeId: TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_CARRIERES, + titreId: titreIdValidator.parse('titreId'), + etapes: [], + }, } console.info = vi.fn() diff --git a/packages/api/src/business/processes/titres-etapes-ordre-update.ts b/packages/api/src/business/processes/titres-etapes-ordre-update.ts index cda09695f..1bd31995f 100644 --- a/packages/api/src/business/processes/titres-etapes-ordre-update.ts +++ b/packages/api/src/business/processes/titres-etapes-ordre-update.ts @@ -10,6 +10,8 @@ import { TitreId } from 'camino-common/src/validators/titres' import { TitreEtapeForMachine, titreEtapeForMachineValidator } from '../rules-demarches/machine-common' import { isNotNullNorUndefinedNorEmpty } from 'camino-common/src/typescript-tools' import { callAndExit } from '../../tools/fp-tools' +import { MachineInfo } from 'camino-common/src/machines' +import { CaminoMachineId } from 'camino-common/src/validators/machine' export const titresEtapesOrdreUpdate = async (pool: Pool, user: UserNotNull, demarcheId?: DemarcheId): Promise<string[]> => { console.info() @@ -29,6 +31,7 @@ export const titresEtapesOrdreUpdateVisibleForTesting = async ( typeId: DemarcheTypeId titreTypeId: TitreTypeId titreId: TitreId + machineId: CaminoMachineId | null } } ): Promise<string[]> => { @@ -38,7 +41,12 @@ export const titresEtapesOrdreUpdateVisibleForTesting = async ( if (isNotNullNorUndefinedNorEmpty(titreDemarche.etapes)) { const etapesMachine = titreDemarche.etapes.map(etape => titreEtapeForMachineValidator.parse(etape)) - const etapes = titreEtapesSortAscByDate(etapesMachine, titreDemarche.id, titreDemarche.typeId, titreDemarche.titreTypeId) + const machineInfo = MachineInfo.withMachineId(titreDemarche.titreTypeId, titreDemarche.typeId, titreDemarche.id, titreDemarche.machineId) + if (!machineInfo.valid) { + throw new Error(`La machine associée à la démarche est incohérente: ${machineInfo.error}`) + } + + const etapes = titreEtapesSortAscByDate(etapesMachine, machineInfo.value) for (let index = 0; index < etapes.length; index++) { const titreEtape = etapes[index] if (titreEtape.ordre !== index + 1) { diff --git a/packages/api/src/business/processes/titres-etapes-statut-update.ts b/packages/api/src/business/processes/titres-etapes-statut-update.ts index 27fa3b835..861f170fa 100644 --- a/packages/api/src/business/processes/titres-etapes-statut-update.ts +++ b/packages/api/src/business/processes/titres-etapes-statut-update.ts @@ -4,6 +4,7 @@ import { getCurrent } from 'camino-common/src/date' import { EtapeStatutId } from 'camino-common/src/static/etapesStatuts' import { getEtapesWithAutomaticStatut, updateEtapeStatut } from '../../database/queries/titres-etapes.queries' import { simpleContenuToFlattenedContenu } from 'camino-common/src/sections' +import { MachineInfo } from 'camino-common/src/machines' export const titresEtapesStatutUpdate = async (pool: Pool): Promise<EtapeId[]> => { console.info() @@ -15,12 +16,17 @@ export const titresEtapesStatutUpdate = async (pool: Pool): Promise<EtapeId[]> = const etapesWithAutomaticStatut = await getEtapesWithAutomaticStatut(pool) for (const etape of etapesWithAutomaticStatut) { + const machineInfo = MachineInfo.withMachineId(etape.titre_type_id, etape.demarche_type_id, etape.demarche_id, etape.demarche_machine_id) + if (!machineInfo.valid) { + throw new Error(`La machine associée à la démarche est incohérente: ${machineInfo.error}`) + } + const newStatut: EtapeStatutId = getStatutId( { ...etape, statutId: etape.etape_statut_id, typeId: etape.type_id, - contenu: simpleContenuToFlattenedContenu(etape.titre_type_id, etape.demarche_type_id, etape.type_id, etape.contenu, etape.heritage_contenu), + contenu: simpleContenuToFlattenedContenu(machineInfo.value, etape.type_id, etape.contenu, etape.heritage_contenu), }, currentDate ) diff --git a/packages/api/src/business/processes/titres-phases-update.test.ts b/packages/api/src/business/processes/titres-phases-update.test.ts index bbc7bec54..9c66d610f 100644 --- a/packages/api/src/business/processes/titres-phases-update.test.ts +++ b/packages/api/src/business/processes/titres-phases-update.test.ts @@ -41,6 +41,7 @@ describe("phases d'un titre", () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: null, id: newDemarcheId('h-cx-courdemanges-1988-oct01'), titreId: newTitreId('h-cx-courdemanges-1988'), typeId: 'oct', @@ -95,6 +96,7 @@ describe("phases d'un titre", () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: null, id: newDemarcheId('h-cx-courdemanges-1988-oct01'), titreId: newTitreId('h-cx-courdemanges-1988'), typeId: 'oct', @@ -150,6 +152,7 @@ describe("phases d'un titre", () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: null, id: newDemarcheId('h-cx-courdemanges-1988-oct01'), titreId: newTitreId('h-cx-courdemanges-1988'), typeId: 'oct', @@ -179,6 +182,7 @@ describe("phases d'un titre", () => { titreStatutId: 'ind', demarches: [ { + machineId: null, id: newDemarcheId('h-cx-courdemanges-1988-oct01'), titreId: newTitreId('h-cx-courdemanges-1988'), typeId: 'oct', @@ -234,6 +238,7 @@ describe("phases d'un titre", () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: null, id: newDemarcheId('h-cx-courdemanges-1988-oct01'), titreId: newTitreId('h-cx-courdemanges-1988'), typeId: 'oct', diff --git a/packages/api/src/business/processes/titres-statut-ids-update.test.ts b/packages/api/src/business/processes/titres-statut-ids-update.test.ts index 2ddc3ae50..0aed42c99 100644 --- a/packages/api/src/business/processes/titres-statut-ids-update.test.ts +++ b/packages/api/src/business/processes/titres-statut-ids-update.test.ts @@ -29,6 +29,7 @@ describe("statut d'un titre", () => { titreStatutId: 'val', demarches: [ { + machineId: null, id: newDemarcheId('m-pr-saint-pierre-1914-oct01'), titreId: newTitreId('m-pr-saint-pierre-1914'), typeId: 'oct', @@ -56,6 +57,7 @@ describe("statut d'un titre", () => { propsTitreEtapesIds: {}, demarches: [ { + machineId: null, id: newDemarcheId('m-pr-saint-pierre-2014-oct01'), titreId: newTitreId('m-pr-saint-pierre-2014'), typeId: 'oct', diff --git a/packages/api/src/business/processes/update-machine-id.queries.ts b/packages/api/src/business/processes/update-machine-id.queries.ts new file mode 100644 index 000000000..752fa8d5f --- /dev/null +++ b/packages/api/src/business/processes/update-machine-id.queries.ts @@ -0,0 +1,18 @@ +import { sql } from '@pgtyped/runtime' +import { z } from 'zod' +import { effectDbQueryAndValidate, EffectDbQueryAndValidateErrors, Redefine } from '../../pg-database' +import { Effect } from 'effect' +import { DemarcheId } from 'camino-common/src/demarche' +import { CaminoError } from 'camino-common/src/zod-tools' +import { CaminoMachineId } from 'camino-common/src/validators/machine' +import { IUpdateMachineIdDbQuery } from './update-machine-id.queries.types' +import { Pool } from 'pg' + +export type UpdateMachineIdErrors = EffectDbQueryAndValidateErrors +export const updateMachineId = (pool: Pool, demarcheId: DemarcheId, machineId: CaminoMachineId | null): Effect.Effect<DemarcheId, CaminoError<UpdateMachineIdErrors>> => { + return effectDbQueryAndValidate(updateMachineIdDb, { demarcheId, machineId }, pool, z.void()).pipe(Effect.map(() => demarcheId)) +} + +const updateMachineIdDb = sql<Redefine<IUpdateMachineIdDbQuery, { machineId: CaminoMachineId | null; demarcheId: DemarcheId }, void>>` +UPDATE titres_demarches SET machine_id = $machineId! WHERE id = $demarcheId! +` diff --git a/packages/api/src/business/processes/update-machine-id.queries.types.ts b/packages/api/src/business/processes/update-machine-id.queries.types.ts new file mode 100644 index 000000000..fed60967c --- /dev/null +++ b/packages/api/src/business/processes/update-machine-id.queries.types.ts @@ -0,0 +1,17 @@ +/** Types generated for queries found in "src/business/processes/update-machine-id.queries.ts" */ + +/** 'UpdateMachineIdDb' parameters type */ +export interface IUpdateMachineIdDbParams { + demarcheId: string; + machineId: string; +} + +/** 'UpdateMachineIdDb' return type */ +export type IUpdateMachineIdDbResult = void; + +/** 'UpdateMachineIdDb' query type */ +export interface IUpdateMachineIdDbQuery { + params: IUpdateMachineIdDbParams; + result: IUpdateMachineIdDbResult; +} + diff --git a/packages/api/src/business/rules-demarches/machines.test.ts b/packages/api/src/business/rules-demarches/machines.test.ts index 63058ce56..eb4f01ea1 100644 --- a/packages/api/src/business/rules-demarches/machines.test.ts +++ b/packages/api/src/business/rules-demarches/machines.test.ts @@ -1,21 +1,46 @@ -import { expect, test } from 'vitest' +import { describe, expect, test } from 'vitest' -import { CaminoMachines, machineFind } from './machines' +import { ApiMachineInfo, demarcheEnregistrementDemandeDateFind } from './machines' import { isNotNullNorUndefined, isNullOrUndefined } from 'camino-common/src/typescript-tools' -import { demarcheEnregistrementDemandeDateFind } from 'camino-common/src/demarche' import { DemarcheWithEtapeForMachinesTest } from '../../tools/demarches/tests-creation' +import { MachineInfo } from 'camino-common/src/machines' +import { toCaminoDate } from 'camino-common/src/date' +import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' const etapesProdSpecifiqueArmAxm = require('./machines-cases.json') // eslint-disable-line // pour regénérer le machines-cases.json: `npm run test:generate-data -w packages/api` test.each(etapesProdSpecifiqueArmAxm as DemarcheWithEtapeForMachinesTest[])('cas réel N°$id', demarche => { const firstEtapeDate = demarcheEnregistrementDemandeDateFind(demarche.etapes.map(etape => ({ ...etape, typeId: etape.etapeTypeId }))) - let machine: CaminoMachines | undefined + let machine: ApiMachineInfo | undefined if (isNotNullNorUndefined(firstEtapeDate)) { - machine = machineFind(demarche.titreTypeId, demarche.demarcheTypeId, demarche.id, firstEtapeDate) + machine = new ApiMachineInfo(MachineInfo.withDate(demarche.titreTypeId, demarche.demarcheTypeId, demarche.id, firstEtapeDate)) } - if (isNullOrUndefined(machine)) { + if (isNullOrUndefined(machine) || isNullOrUndefined(machine.machine)) { throw new Error(`Impossible de trouver une machine alors qu'on aurait du avoir ${demarche.machineId}, ${demarche.id}`) } - machine.interpretMachine(demarche.etapes) - expect(machine.demarcheStatut(demarche.etapes), `${demarche.machineId}`).toStrictEqual(demarche.statut) + machine.machine.interpretMachine(demarche.etapes) + expect(machine.machine.demarcheStatut(demarche.etapes), `${demarche.machineId}`).toStrictEqual(demarche.statut) +}) + +describe('demarcheEnregistrementDemandeDateFind', () => { + test("pas d'étapes", () => { + expect(demarcheEnregistrementDemandeDateFind([])).toBe(null) + }) + + test('un enregistrement de la demande', () => { + expect( + demarcheEnregistrementDemandeDateFind([ + { typeId: ETAPES_TYPES.demande, date: toCaminoDate('2020-01-01') }, + { typeId: ETAPES_TYPES.enregistrementDeLaDemande, date: toCaminoDate('2024-01-01') }, + ]) + ).toBe(toCaminoDate('2024-01-01')) + }) + test('sans enregistrement de la demande', () => { + expect( + demarcheEnregistrementDemandeDateFind([ + { typeId: ETAPES_TYPES.demande, date: toCaminoDate('2020-01-01') }, + { typeId: ETAPES_TYPES.abrogationDeLaDecision, date: toCaminoDate('2024-01-01') }, + ]) + ).toBe(toCaminoDate('2020-01-01')) + }) }) diff --git a/packages/api/src/business/rules-demarches/machines.ts b/packages/api/src/business/rules-demarches/machines.ts index 19c42773b..638291ba8 100644 --- a/packages/api/src/business/rules-demarches/machines.ts +++ b/packages/api/src/business/rules-demarches/machines.ts @@ -6,30 +6,66 @@ import { AxmProMachine } from './axm/pro.machine' import { PrmOctMachine } from './prm/oct.machine' import { ProcedureSimplifieeMachine } from './procedure-simplifiee/procedure-simplifiee.machine' import { ProcedureSpecifiqueMachine } from './procedure-specifique/procedure-specifique.machine' -import { machineIdFind, type CaminoMachineId } from 'camino-common/src/machines' +import { MachineInfo } from 'camino-common/src/machines' import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' -import { FirstEtapeDate } from 'camino-common/src/date' import { DemarcheId } from 'camino-common/src/demarche' -import { isNullOrUndefined } from 'camino-common/src/typescript-tools' +import { CaminoMachineId } from 'camino-common/src/validators/machine' +import { CaminoDate, FirstEtapeDate, firstEtapeDateValidator } from 'camino-common/src/date' +import { EtapeTypeId, ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' +import { isNullOrUndefinedOrEmpty, isNotNullNorUndefined, toSorted } from 'camino-common/src/typescript-tools' +import { NonEmptyArray } from 'zod-validation-error' const machines = { - ArmOct: (titreTypeId, demarcheTypeId) => new ArmOctMachine(titreTypeId, demarcheTypeId), - ArmRenPro: (titreTypeId, demarcheTypeId) => new ArmRenProMachine(titreTypeId, demarcheTypeId), - AxmOct: (titreTypeId, demarcheTypeId) => new AxmOctMachine(titreTypeId, demarcheTypeId), - AxmPro: (titreTypeId, demarcheTypeId) => new AxmProMachine(titreTypeId, demarcheTypeId), - PrmOct: (titreTypeId, demarcheTypeId) => new PrmOctMachine(titreTypeId, demarcheTypeId), + AncienLogigrammeOctroiARM: (titreTypeId, demarcheTypeId) => new ArmOctMachine(titreTypeId, demarcheTypeId), + AncienLogigrammeRenonciationEtProlongationARM: (titreTypeId, demarcheTypeId) => new ArmRenProMachine(titreTypeId, demarcheTypeId), + AncienLogigrammeOctroiAXM: (titreTypeId, demarcheTypeId) => new AxmOctMachine(titreTypeId, demarcheTypeId), + AncienLogigrammeProlongationAXM: (titreTypeId, demarcheTypeId) => new AxmProMachine(titreTypeId, demarcheTypeId), + AncienLogigrammeOctroiPRM: (titreTypeId, demarcheTypeId) => new PrmOctMachine(titreTypeId, demarcheTypeId), ProcedureSimplifiee: (titreTypeId, demarcheTypeId) => new ProcedureSimplifieeMachine(titreTypeId, demarcheTypeId), ProcedureSpecifique: (titreTypeId, demarcheTypeId) => new ProcedureSpecifiqueMachine(titreTypeId, demarcheTypeId), } as const satisfies Record<CaminoMachineId, (titreTypeId: TitreTypeId, demarcheTypeId: DemarcheTypeId) => CaminoMachines> -export const machineFind = (titreTypeId: TitreTypeId, demarcheTypeId: DemarcheTypeId, demarcheId: DemarcheId, date: FirstEtapeDate): CaminoMachines | undefined => { - const machineId = machineIdFind(titreTypeId, demarcheTypeId, demarcheId, date) - if (isNullOrUndefined(machineId)) { - return undefined +export class ApiMachineInfo { + private _machineInfo: MachineInfo + private _machine: CaminoMachines | undefined + public constructor(machineInfo: MachineInfo) { + this._machineInfo = machineInfo + this._machine = machineInfo.machineId === undefined ? undefined : machines[machineInfo.machineId](machineInfo.titreTypeId, machineInfo.demarcheTypeId) + } + + get machineId(): CaminoMachineId | undefined { + return this._machineInfo.machineId + } + get titreTypeId(): TitreTypeId { + return this._machineInfo.titreTypeId + } + get demarcheTypeId(): DemarcheTypeId { + return this._machineInfo.demarcheTypeId + } + get demarcheId(): DemarcheId { + return this._machineInfo.demarcheId + } + get machine(): CaminoMachines | undefined { + return this._machine } - return getMachineFromId({ machineId, titreTypeId, demarcheTypeId }) } -export const getMachineFromId = (entry: { machineId: CaminoMachineId; titreTypeId: TitreTypeId; demarcheTypeId: DemarcheTypeId } | undefined): CaminoMachines | undefined => - entry === undefined ? undefined : machines[entry.machineId](entry.titreTypeId, entry.demarcheTypeId) export type CaminoMachines = ArmOctMachine | AxmOctMachine | AxmProMachine | ArmRenProMachine | PrmOctMachine | ProcedureSimplifieeMachine | ProcedureSpecifiqueMachine + +type DemarcheEnregistrementDemandeDateFindEtape = { date: CaminoDate; typeId: EtapeTypeId } +export function demarcheEnregistrementDemandeDateFind<T extends DemarcheEnregistrementDemandeDateFindEtape[] | NonEmptyArray<DemarcheEnregistrementDemandeDateFindEtape>>( + titreEtapes: T | undefined +): T extends [DemarcheEnregistrementDemandeDateFindEtape, ...DemarcheEnregistrementDemandeDateFindEtape[]] ? FirstEtapeDate : FirstEtapeDate | null +export function demarcheEnregistrementDemandeDateFind(titreEtapes: DemarcheEnregistrementDemandeDateFindEtape[] | undefined): null | FirstEtapeDate { + if (isNullOrUndefinedOrEmpty(titreEtapes)) { + return null + } + + const titreEtapeDemande = titreEtapes.find(te => te.typeId === ETAPES_TYPES.enregistrementDeLaDemande) + + if (isNotNullNorUndefined(titreEtapeDemande)) { + return firstEtapeDateValidator.parse(titreEtapeDemande.date) + } + + return firstEtapeDateValidator.parse(toSorted(titreEtapes.map(te => te.date))[0]) +} diff --git a/packages/api/src/business/rules/titre-activites-build.test.ts b/packages/api/src/business/rules/titre-activites-build.test.ts index 1fa74fe87..7a53ca6eb 100644 --- a/packages/api/src/business/rules/titre-activites-build.test.ts +++ b/packages/api/src/business/rules/titre-activites-build.test.ts @@ -55,6 +55,7 @@ describe("construction des activités d'un titre", () => { test('crée des activités', () => { const titreActivitesA = titreActivitesBuild(ACTIVITES_TYPES_IDS["rapport d'exploitation (permis et concessions M)"], [toCaminoAnnee(2018)], aujourdhui, titreId, 'pxm', [ { + machineId: null, id: newDemarcheId('demarche-id'), titreId: newTitreId('titreId'), statutId: 'acc', diff --git a/packages/api/src/business/rules/titre-date-demande-find.test.ts b/packages/api/src/business/rules/titre-date-demande-find.test.ts index a58e9777c..d691d3c62 100644 --- a/packages/api/src/business/rules/titre-date-demande-find.test.ts +++ b/packages/api/src/business/rules/titre-date-demande-find.test.ts @@ -26,6 +26,7 @@ const titreDemarcheOctEtapeMen = [ const titreDemarcheOctSansEtapes = [ { + machineId: null, id: newDemarcheId('h-cx-courdemanges-1988-oct01'), titreId: newTitreId('h-cx-courdemanges-1988'), typeId: 'oct', diff --git a/packages/api/src/business/rules/titre-demarche-annulation-date-fin-find.test.ts b/packages/api/src/business/rules/titre-demarche-annulation-date-fin-find.test.ts index 307efb2d5..35b4106dc 100644 --- a/packages/api/src/business/rules/titre-demarche-annulation-date-fin-find.test.ts +++ b/packages/api/src/business/rules/titre-demarche-annulation-date-fin-find.test.ts @@ -7,9 +7,10 @@ import { describe, expect, test } from 'vitest' import { ETAPE_IS_NOT_BROUILLON } from 'camino-common/src/etape' import { TITRES_TYPES_IDS } from 'camino-common/src/static/titresTypes' import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes' -import { titreIdValidator } from 'camino-common/src/validators/titres' import { NonEmptyArray } from 'camino-common/src/typescript-tools' import { ETAPES_STATUTS, EtapeStatutId } from 'camino-common/src/static/etapesStatuts' +import { MachineInfo } from 'camino-common/src/machines' +import { demarcheEnregistrementDemandeDateFind } from '../rules-demarches/machines' describe("date de fin d'une démarche d'annulation", () => { test.each<{ typeId: EtapeTypeId; statutId: EtapeStatutId }>([ { typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: ETAPES_STATUTS.ACCEPTE }, @@ -30,12 +31,10 @@ describe("date de fin d'une démarche d'annulation", () => { }, ] as const satisfies ITitreEtape[] expect( - titreDemarcheAnnulationDateFinFind(TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE, { - id: titreDemarcheId, - titreId: titreIdValidator.parse('titreId'), - typeId: DEMARCHES_TYPES_IDS.Retrait, - etapes: titreDemarcheAnnulationEtapes, - }) + titreDemarcheAnnulationDateFinFind( + MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE, DEMARCHES_TYPES_IDS.Retrait, titreDemarcheId, demarcheEnregistrementDemandeDateFind(titreDemarcheAnnulationEtapes)), + titreDemarcheAnnulationEtapes + ) ).toEqual('1999-05-21') }) // TODO 2025-01-15 cet id est ignoré explicitement dans la machine pour utiliser TDE, test à virer quand on arrête de faire des avenant dans les octrois mais qu'on fait des prolongations (tache à POH) @@ -60,12 +59,16 @@ describe("date de fin d'une démarche d'annulation", () => { }, ] expect( - titreDemarcheAnnulationDateFinFind(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, { - id: titreDemarcheId, - titreId: titreIdValidator.parse('titreId'), - typeId: DEMARCHES_TYPES_IDS.Octroi, - etapes: titreDemarcheAnnulationEtapesDateFin, - }) + titreDemarcheAnnulationDateFinFind( + MachineInfo.withDate( + TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + DEMARCHES_TYPES_IDS.Octroi, + titreDemarcheId, + demarcheEnregistrementDemandeDateFind(titreDemarcheAnnulationEtapesDateFin) + ), + + titreDemarcheAnnulationEtapesDateFin + ) ).toEqual('2013-05-25') } ) @@ -87,12 +90,15 @@ describe("date de fin d'une démarche d'annulation", () => { }, ] expect( - titreDemarcheAnnulationDateFinFind(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, { - id: titreDemarcheIdExcluDesOctroisDArm, - titreId: titreIdValidator.parse('titreId'), - typeId: DEMARCHES_TYPES_IDS.Octroi, - etapes: titreDemarcheACOFaitEtapesDateFin, - }) + titreDemarcheAnnulationDateFinFind( + MachineInfo.withDate( + TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + DEMARCHES_TYPES_IDS.Octroi, + titreDemarcheIdExcluDesOctroisDArm, + demarcheEnregistrementDemandeDateFind(titreDemarcheACOFaitEtapesDateFin) + ), + titreDemarcheACOFaitEtapesDateFin + ) ).toEqual('2013-05-25') }) }) diff --git a/packages/api/src/business/rules/titre-demarche-annulation-date-fin-find.ts b/packages/api/src/business/rules/titre-demarche-annulation-date-fin-find.ts index ce549bc40..909a0b592 100644 --- a/packages/api/src/business/rules/titre-demarche-annulation-date-fin-find.ts +++ b/packages/api/src/business/rules/titre-demarche-annulation-date-fin-find.ts @@ -1,26 +1,25 @@ import { CaminoDate } from 'camino-common/src/date' import { titreEtapesSortAscByOrdre, titreEtapesSortDescByOrdre } from '../utils/titre-etapes-sort' -import { TitreDemarchePhaseFindWithEtapes, TitreEtapePhaseFind } from './titre-phases-find' +import { TitreEtapePhaseFind } from './titre-phases-find' import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' import { ETAPES_STATUTS } from 'camino-common/src/static/etapesStatuts' -import { isNotNullNorUndefined } from 'camino-common/src/typescript-tools' -import { machineFind } from '../rules-demarches/machines' -import { demarcheEnregistrementDemandeDateFind } from 'camino-common/src/demarche' -import { TitreTypeId } from 'camino-common/src/static/titresTypes' +import { isNotNullNorUndefined, NonEmptyArray } from 'camino-common/src/typescript-tools' import { toMachineEtapes } from '../rules-demarches/machine-common' import { demarcheStatutIdsSuccess } from 'camino-common/src/static/demarchesStatuts' +import { MachineInfo } from 'camino-common/src/machines' +import { ApiMachineInfo } from '../rules-demarches/machines' -export const titreDemarcheAnnulationDateFinFind = (titreTypeId: TitreTypeId, demarche: Omit<TitreDemarchePhaseFindWithEtapes, 'fullEtapes'>): CaminoDate | null | undefined => { - const machine = machineFind(titreTypeId, demarche.typeId, demarche.id, demarcheEnregistrementDemandeDateFind(demarche.etapes)) - if (isNotNullNorUndefined(machine)) { - const statut = machine.demarcheStatut(toMachineEtapes(demarche.etapes)) +export const titreDemarcheAnnulationDateFinFind = (machineInfo: MachineInfo, etapes: NonEmptyArray<TitreEtapePhaseFind>): CaminoDate | null | undefined => { + const machine = new ApiMachineInfo(machineInfo) + if (isNotNullNorUndefined(machine.machine)) { + const statut = machine.machine.demarcheStatut(toMachineEtapes(etapes)) if (demarcheStatutIdsSuccess.has(statut.demarcheStatut)) { if ('demarcheDateEffet' in statut) { return statut.demarcheDateEffet } - throw new Error(`Pas de date d'effet trouvée pour la démarche d'annulation https://camino.beta.gouv.fr/demarches/${demarche.id}`) + throw new Error(`Pas de date d'effet trouvée pour la démarche d'annulation https://camino.beta.gouv.fr/demarches/${machineInfo.demarcheId}`) } return null } else { @@ -32,7 +31,7 @@ export const titreDemarcheAnnulationDateFinFind = (titreTypeId: TitreTypeId, dem (te.typeId === ETAPES_TYPES.avenantALautorisationDeRechercheMiniere && te.statutId === ETAPES_STATUTS.FAIT) // la dernière étape qui valide l’annulation et qui contient une date de fin - const etapeAnnulationHasDateFin = titreEtapesSortDescByOrdre(demarche.etapes).find(te => isNotNullNorUndefined(te.dateFin) && etapeAnnulationValideCheck(te)) + const etapeAnnulationHasDateFin = titreEtapesSortDescByOrdre(etapes).find(te => isNotNullNorUndefined(te.dateFin) && etapeAnnulationValideCheck(te)) // si la démarche contient une date de fin if (etapeAnnulationHasDateFin) { @@ -41,7 +40,7 @@ export const titreDemarcheAnnulationDateFinFind = (titreTypeId: TitreTypeId, dem // sinon, // trouve la première étape qui valide l’annulation - const etapeAnnulation = titreEtapesSortAscByOrdre(demarche.etapes).find(etapeAnnulationValideCheck) + const etapeAnnulation = titreEtapesSortAscByOrdre(etapes).find(etapeAnnulationValideCheck) // la date de fin est la date de l'étape return etapeAnnulation?.date ?? null diff --git a/packages/api/src/business/rules/titre-demarche-public-find.test.ts b/packages/api/src/business/rules/titre-demarche-public-find.test.ts index a336a03a9..dff052556 100644 --- a/packages/api/src/business/rules/titre-demarche-public-find.test.ts +++ b/packages/api/src/business/rules/titre-demarche-public-find.test.ts @@ -3,12 +3,13 @@ import { ITitreEtape } from '../../types' import { titreDemarchePublicFind } from './titre-demarche-public-find' import { ETAPES_TYPES, EtapeTypeId } from 'camino-common/src/static/etapesTypes' import { newDemarcheId, newEtapeId, newTitreId } from '../../database/models/_format/id-create' -import { toCaminoDate } from 'camino-common/src/date' +import { firstEtapeDateValidator, toCaminoDate } from 'camino-common/src/date' import { describe, expect, test } from 'vitest' import { DEMARCHES_TYPES_IDS, DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' import { ETAPE_IS_NOT_BROUILLON } from 'camino-common/src/etape' import { TITRES_TYPES_IDS } from 'camino-common/src/static/titresTypes' import { ETAPES_STATUTS } from 'camino-common/src/static/etapesStatuts' +import { MachineInfo } from 'camino-common/src/machines' const etapesBuild = (etapesProps: Partial<ITitreEtape>[]) => etapesProps.map( (etapeProps, i) => @@ -20,23 +21,19 @@ const etapesBuild = (etapesProps: Partial<ITitreEtape>[]) => ...etapeProps, ordre: i + 1, date: toCaminoDate('0001-01-01'), + demarcheIdsConsentement: [], }) as unknown as ITitreEtape ) describe("publicité d'une démarche", () => { test("une démarche sans étape n'est pas publique", () => { expect( - titreDemarchePublicFind( - { - id: newDemarcheId(), - typeId: DEMARCHES_TYPES_IDS.Octroi, - etapes: [], - titreId: newTitreId('titreId'), - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { + etapes: [], + titreId: newTitreId('titreId'), + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + }) ).toMatchObject({ publicLecture: false, entreprisesLecture: false, @@ -46,15 +43,13 @@ describe("publicité d'une démarche", () => { test("une démarche d'octroi sans étape décisive n'est pas publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - id: newDemarcheId(), - typeId: DEMARCHES_TYPES_IDS.Octroi, etapes: etapesBuild([{ typeId: ETAPES_TYPES.decisionDeLaMissionAutoriteEnvironnementale_ExamenAuCasParCasDuProjet_ }]), titreId: newTitreId('titreId'), demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: false, entreprisesLecture: false }) }) @@ -62,15 +57,13 @@ describe("publicité d'une démarche", () => { test("une démarche de retrait dont l'étape la plus récente est saisine du préfet est publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), etapes: etapesBuild([{ typeId: ETAPES_TYPES.saisineDuPrefet }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: false, entreprisesLecture: false }) }) @@ -78,15 +71,13 @@ describe("publicité d'une démarche", () => { test("une démarche de retrait dont l'étape la plus récente est saisine du préfet est publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Retrait, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Retrait, - id: newDemarcheId(), demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), etapes: etapesBuild([{ typeId: ETAPES_TYPES.saisineDuPrefet }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: true, entreprisesLecture: true }) }) @@ -94,15 +85,13 @@ describe("publicité d'une démarche", () => { test("une démarche de déchéance dont l'étape la plus récente est saisine du préfet est publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Decheance, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Decheance, - id: newDemarcheId(), demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), etapes: etapesBuild([{ typeId: ETAPES_TYPES.saisineDuPrefet }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: true, entreprisesLecture: true }) }) @@ -110,178 +99,132 @@ describe("publicité d'une démarche", () => { test("une démarche dont l'étape la plus récente est demande est visible uniquement par l'entreprise", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), etapes: etapesBuild([{ typeId: ETAPES_TYPES.demande }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: false, entreprisesLecture: true }) }) test("une démarche d'une machine simplifiée dont l'étape la plus récente est décision de l'administration est visible", () => { expect( - titreDemarchePublicFind( - { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), - demarcheDateDebut: toCaminoDate('2023-01-01'), - demarcheDateFin: toCaminoDate('2026-01-01'), - etapes: etapesBuild([{ typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, date: toCaminoDate('2023-01-01'), statutId: ETAPES_STATUTS.ACCEPTE, isBrouillon: ETAPE_IS_NOT_BROUILLON }]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_GEOTHERMIE - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_GEOTHERMIE, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2023-01-01')), { + demarcheDateDebut: toCaminoDate('2023-01-01'), + demarcheDateFin: toCaminoDate('2026-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, date: toCaminoDate('2023-01-01'), statutId: ETAPES_STATUTS.ACCEPTE, isBrouillon: ETAPE_IS_NOT_BROUILLON }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true, entreprisesLecture: true }) }) test("une démarche dont l'étape la plus récente est classement sans suite n'est pas publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), etapes: etapesBuild([{ typeId: ETAPES_TYPES.classementSansSuite }, { typeId: ETAPES_TYPES.demande }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: false }) }) test("une démarche d'un titre AXM dont l'étape la plus récente est classement sans suite ne change pas de visibilité", () => { expect( - titreDemarchePublicFind( - { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - etapes: etapesBuild([{ typeId: ETAPES_TYPES.recevabiliteDeLaDemande, date: toCaminoDate('2000-01-01') }, { typeId: ETAPES_TYPES.classementSansSuite }]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.recevabiliteDeLaDemande, date: toCaminoDate('2000-01-01') }, { typeId: ETAPES_TYPES.classementSansSuite }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) }) test("une démarche d'un titre ARM dont l'étape la plus récente est classement sans suite ne change pas de visibilité", () => { expect( - titreDemarchePublicFind( - { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - etapes: etapesBuild([ - { typeId: ETAPES_TYPES.saisineDeLaCommissionDesAutorisationsDeRecherchesMinieres_CARM_, date: toCaminoDate('2000-01-01') }, - { typeId: ETAPES_TYPES.classementSansSuite }, - ]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2000-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.saisineDeLaCommissionDesAutorisationsDeRecherchesMinieres_CARM_, date: toCaminoDate('2000-01-01') }, { typeId: ETAPES_TYPES.classementSansSuite }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) }) test("une démarche d'un titre ARM dont l'étape la plus récente est désistement du demandeur est publique", () => { expect( - titreDemarchePublicFind( - { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - etapes: etapesBuild([{ typeId: ETAPES_TYPES.desistementDuDemandeur, date: toCaminoDate('2000-01-01') }]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2000-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.desistementDuDemandeur, date: toCaminoDate('2000-01-01') }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) }) test("une démarche d'un titre AXM dont l'étape la plus récente est désistement du demandeur est publique", () => { expect( - titreDemarchePublicFind( - { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - etapes: etapesBuild([{ typeId: ETAPES_TYPES.desistementDuDemandeur, date: toCaminoDate('2000-01-01') }]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.desistementDuDemandeur, date: toCaminoDate('2000-01-01') }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) }) test("une démarche ne pouvant pas faire l'objet d'une mise en concurrence dont l'étape la plus récente est recevabilité est publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Prolongation1, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Prolongation1, - id: newDemarcheId(), demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), etapes: etapesBuild([{ typeId: ETAPES_TYPES.recevabiliteDeLaDemande }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: true }) }) test("une démarche d'un titre ARM ne pouvant pas faire l'objet d'une mise en concurrence dont l'étape la plus récente est recevabilité n'est pas publique", () => { expect( - titreDemarchePublicFind( - { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - etapes: etapesBuild([{ typeId: ETAPES_TYPES.recevabiliteDeLaDemande, date: toCaminoDate('2000-01-01') }]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2000-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.recevabiliteDeLaDemande, date: toCaminoDate('2000-01-01') }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: false }) }) test("une démarche pouvant faire l'objet d'une mise en concurrence dont l'étape la plus récente est recevabilité n'est pas publique", () => { expect( - titreDemarchePublicFind( - { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - etapes: etapesBuild([{ typeId: ETAPES_TYPES.recevabiliteDeLaDemande }]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.CONCESSION_GEOTHERMIE - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_GEOTHERMIE, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.recevabiliteDeLaDemande }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: false }) }) test("une démarche dont l'étape la plus récente est mise en concurrence au JORF est publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), etapes: etapesBuild([{ typeId: ETAPES_TYPES.avisDeMiseEnConcurrenceAuJORF }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: true }) }) @@ -289,15 +232,13 @@ describe("publicité d'une démarche", () => { test("une démarche dont l'étape la plus récente est publication de l'avis de décision implicite (historique) est publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), etapes: etapesBuild([{ typeId: ETAPES_TYPES.publicationDeLavisDeDecisionImplicite }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: true }) }) @@ -305,79 +246,60 @@ describe("publicité d'une démarche", () => { test("une démarche dont l'étape la plus récente est consultation du public est publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), etapes: etapesBuild([{ typeId: ETAPES_TYPES.consultationDuPublic }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: true }) }) test("une démarche d'un titre ARM dont l'étape la plus récente est décision de l'ONF peu importe son statut (historique) est publique", () => { expect( - titreDemarchePublicFind( - { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - etapes: etapesBuild([{ typeId: ETAPES_TYPES.decisionDeLOfficeNationalDesForets, date: toCaminoDate('2000-01-01') }]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2000-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.decisionDeLOfficeNationalDesForets, date: toCaminoDate('2000-01-01') }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) }) test("une démarche d'un titre ARM dont l'étape la plus récente est commission ARM peu importe son statut (historique) est publique", () => { expect( - titreDemarchePublicFind( - { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - etapes: etapesBuild([{ typeId: ETAPES_TYPES.avisDeLaCommissionDesAutorisationsDeRecherchesMinieres_CARM_, date: toCaminoDate('2000-01-01') }]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2000-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.avisDeLaCommissionDesAutorisationsDeRecherchesMinieres_CARM_, date: toCaminoDate('2000-01-01') }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) }) test("une démarche d'un titre ARM dont l'étape la plus récente est saisine de la commission ARM est publique", () => { expect( - titreDemarchePublicFind( - { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - etapes: etapesBuild([{ typeId: ETAPES_TYPES.saisineDeLaCommissionDesAutorisationsDeRecherchesMinieres_CARM_, date: toCaminoDate('2000-01-01') }]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2000-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.saisineDeLaCommissionDesAutorisationsDeRecherchesMinieres_CARM_, date: toCaminoDate('2000-01-01') }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) }) test("une démarche dont l'étape la plus récente est décision implicite au statut accepté est publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), etapes: etapesBuild([{ typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: ETAPES_STATUTS.ACCEPTE_DECISION_IMPLICITE }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: true }) }) @@ -385,9 +307,8 @@ describe("publicité d'une démarche", () => { test("une démarche dont l'étape la plus récente est décision implicite au statut rejeté n'est pas publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, - id: newDemarcheId(), demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), etapes: etapesBuild([ @@ -395,8 +316,7 @@ describe("publicité d'une démarche", () => { { typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: ETAPES_STATUTS.REJETE_DECISION_IMPLICITE, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2021-01-02') }, ]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: false }) }) @@ -404,66 +324,52 @@ describe("publicité d'une démarche", () => { test("une démarche d'un titre non AXM dont l'étape la plus récente est décision de l'administration au statut rejeté n'est pas publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), etapes: etapesBuild([{ typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: ETAPES_STATUTS.REJETE }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: false }) }) test("une démarche d'un titre AXM dont l'étape la plus récente est décision de l'administration au statut rejeté est publique", () => { expect( - titreDemarchePublicFind( - { - typeId: DEMARCHES_TYPES_IDS.Octroi, - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), - etapes: etapesBuild([ - { typeId: ETAPES_TYPES.recevabiliteDeLaDemande, date: toCaminoDate('2000-01-01') }, - { typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: ETAPES_STATUTS.REJETE }, - ]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([ + { typeId: ETAPES_TYPES.recevabiliteDeLaDemande, date: toCaminoDate('2000-01-01') }, + { typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: ETAPES_STATUTS.REJETE }, + ]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) }) test("une démarche d'un titre AXM dont l'étape la plus récente est décision de l'administration au statut accepté est publique", () => { expect( - titreDemarchePublicFind( - { - typeId: DEMARCHES_TYPES_IDS.Octroi, - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), - etapes: etapesBuild([{ typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: ETAPES_STATUTS.ACCEPTE, date: toCaminoDate('2000-01-01') }]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: ETAPES_STATUTS.ACCEPTE, date: toCaminoDate('2000-01-01') }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) }) test("une démarche dont l'étape la plus récente est publication de décision au JORF au statut au statut accepté publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), etapes: etapesBuild([{ typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: ETAPES_STATUTS.ACCEPTE }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: true }) }) @@ -471,15 +377,13 @@ describe("publicité d'une démarche", () => { test("une démarche dont l'étape la plus récente est décision de l'autorité administrative est publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), etapes: etapesBuild([{ typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: true }) }) @@ -487,15 +391,13 @@ describe("publicité d'une démarche", () => { test("une démarche dont l'étape la plus récente est publication de décision unilatérale est publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), etapes: etapesBuild([{ typeId: ETAPES_TYPES.publicationDeDecisionAuJORF }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: true }) }) @@ -503,63 +405,49 @@ describe("publicité d'une démarche", () => { test("une démarche dont l'étape la plus récente est publication de décision au recueil des actes administratifs est publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), etapes: etapesBuild([{ typeId: ETAPES_TYPES.publicationDeDecisionAuRecueilDesActesAdministratifs }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: true }) }) test("une démarche d'un titre ARM dont l'étape la plus récente est signature de l'autorisation de recherche minière est publique", () => { expect( - titreDemarchePublicFind( - { - typeId: DEMARCHES_TYPES_IDS.Octroi, - demarcheDateDebut: toCaminoDate('2000-01-01'), - demarcheDateFin: toCaminoDate('2001-01-01'), - id: newDemarcheId(), - etapes: etapesBuild([{ typeId: ETAPES_TYPES.signatureDeLautorisationDeRechercheMiniere, date: toCaminoDate('2000-01-01') }]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2000-01-01')), { + demarcheDateDebut: toCaminoDate('2000-01-01'), + demarcheDateFin: toCaminoDate('2001-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.signatureDeLautorisationDeRechercheMiniere, date: toCaminoDate('2000-01-01') }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) }) test("une démarche d'un titre ARM dont l'étape la plus récente est signature de l'avenant à l'autorisation de recherche minière est publique", () => { expect( - titreDemarchePublicFind( - { - typeId: DEMARCHES_TYPES_IDS.Octroi, - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), - etapes: etapesBuild([{ typeId: ETAPES_TYPES.signatureDeLautorisationDeRechercheMiniere, date: toCaminoDate('2000-01-01') }]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2000-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.signatureDeLautorisationDeRechercheMiniere, date: toCaminoDate('2000-01-01') }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) }) test("une démarche dont l'étape la plus récente est décision d'annulation par le juge administratif est publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), etapes: etapesBuild([{ typeId: ETAPES_TYPES.decisionDuJugeAdministratif, statutId: ETAPES_STATUTS.FAVORABLE }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: true }) }) @@ -567,15 +455,13 @@ describe("publicité d'une démarche", () => { test("une démarche dont l'étape la plus récente est décision d'annulation par le juge administratif au statut fait n'est pas publique", () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), etapes: etapesBuild([{ typeId: ETAPES_TYPES.decisionDuJugeAdministratif, statutId: ETAPES_STATUTS.FAIT }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: false }) }) @@ -584,33 +470,23 @@ describe("publicité d'une démarche", () => { "une démarche %s dont l'étape la plus récente est le dépot de la demande n'est pas publique", demarcheTypeId => { expect( - titreDemarchePublicFind( - { - typeId: demarcheTypeId, - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), - etapes: etapesBuild([{ typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2017-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, demarcheTypeId, newDemarcheId(), firstEtapeDateValidator.parse('2017-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2017-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: false }) expect( - titreDemarchePublicFind( - { - typeId: demarcheTypeId, - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), - etapes: etapesBuild([ - { typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - { typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-02'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - ]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, demarcheTypeId, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([ + { typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + { typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-02'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + ]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: false }) } ) @@ -619,35 +495,25 @@ describe("publicité d'une démarche", () => { "une démarche %s dont l'étape la plus récente est recevabilité de la demande est publique", demarcheTypeId => { expect( - titreDemarchePublicFind( - { - typeId: demarcheTypeId, - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), - etapes: etapesBuild([{ typeId: ETAPES_TYPES.recevabiliteDeLaDemande, date: toCaminoDate('2017-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, demarcheTypeId, newDemarcheId(), firstEtapeDateValidator.parse('2017-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.recevabiliteDeLaDemande, date: toCaminoDate('2017-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) expect( - titreDemarchePublicFind( - { - typeId: demarcheTypeId, - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), - etapes: etapesBuild([ - { typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - { typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-02'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - { typeId: ETAPES_TYPES.recevabiliteDeLaDemande, statutId: ETAPES_STATUTS.FAVORABLE, date: toCaminoDate('2020-01-03'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - ]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, demarcheTypeId, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([ + { typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + { typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-02'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + { typeId: ETAPES_TYPES.recevabiliteDeLaDemande, statutId: ETAPES_STATUTS.FAVORABLE, date: toCaminoDate('2020-01-03'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + ]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) } ) @@ -656,38 +522,33 @@ describe("publicité d'une démarche", () => { "une démarche %s dont l'étape la plus récente est l’expertise de l’onf est publique", demarcheTypeId => { expect( - titreDemarchePublicFind( - { - typeId: demarcheTypeId, - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), - etapes: etapesBuild([ - { typeId: ETAPES_TYPES.recevabiliteDeLaDemande, date: toCaminoDate('2017-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - { typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, date: toCaminoDate('2017-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - ]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, demarcheTypeId, newDemarcheId(), firstEtapeDateValidator.parse('2017-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([ + { typeId: ETAPES_TYPES.recevabiliteDeLaDemande, date: toCaminoDate('2017-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + { typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, date: toCaminoDate('2017-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + ]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) expect( - titreDemarchePublicFind( - { - typeId: demarcheTypeId, - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), - etapes: etapesBuild([ - { typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - { typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-02'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - { typeId: ETAPES_TYPES.recevabiliteDeLaDemande, statutId: ETAPES_STATUTS.FAVORABLE, date: toCaminoDate('2020-01-03'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - { typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-05'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - ]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, demarcheTypeId, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([ + { typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + { typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-02'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + { typeId: ETAPES_TYPES.recevabiliteDeLaDemande, statutId: ETAPES_STATUTS.FAVORABLE, date: toCaminoDate('2020-01-03'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + { + typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, + statutId: ETAPES_STATUTS.FAIT, + date: toCaminoDate('2020-01-05'), + isBrouillon: ETAPE_IS_NOT_BROUILLON, + }, + ]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) } ) @@ -696,35 +557,25 @@ describe("publicité d'une démarche", () => { "une démarche %s dont l'étape la plus récente est la décision de classement sans suite est publique", demarcheTypeId => { expect( - titreDemarchePublicFind( - { - typeId: demarcheTypeId, - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), - etapes: etapesBuild([{ typeId: ETAPES_TYPES.classementSansSuite, date: toCaminoDate('2017-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, demarcheTypeId, newDemarcheId(), firstEtapeDateValidator.parse('2017-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.classementSansSuite, date: toCaminoDate('2017-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON, statutId: ETAPES_STATUTS.FAIT }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) expect( - titreDemarchePublicFind( - { - typeId: demarcheTypeId, - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), - etapes: etapesBuild([ - { typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - { typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-02'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - { typeId: ETAPES_TYPES.recevabiliteDeLaDemande, statutId: ETAPES_STATUTS.FAVORABLE, date: toCaminoDate('2020-01-03'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - { typeId: ETAPES_TYPES.classementSansSuite, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-05'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - ]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, demarcheTypeId, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([ + { typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + { typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-02'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + { typeId: ETAPES_TYPES.recevabiliteDeLaDemande, statutId: ETAPES_STATUTS.FAVORABLE, date: toCaminoDate('2020-01-03'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + { typeId: ETAPES_TYPES.classementSansSuite, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-05'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + ]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) } ) @@ -734,35 +585,25 @@ describe("publicité d'une démarche", () => { demarcheTypeId => { // sans machine expect( - titreDemarchePublicFind( - { - typeId: demarcheTypeId, - demarcheDateDebut: toCaminoDate('2017-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), - etapes: etapesBuild([{ typeId: ETAPES_TYPES.desistementDuDemandeur, date: toCaminoDate('2017-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, demarcheTypeId, newDemarcheId(), firstEtapeDateValidator.parse('2017-01-01')), { + demarcheDateDebut: toCaminoDate('2017-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([{ typeId: ETAPES_TYPES.desistementDuDemandeur, date: toCaminoDate('2017-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) // avec machine expect( - titreDemarchePublicFind( - { - typeId: demarcheTypeId, - demarcheDateDebut: toCaminoDate('2020-01-01'), - demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), - etapes: etapesBuild([ - { typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - { typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-02'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - { typeId: ETAPES_TYPES.desistementDuDemandeur, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-05'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, - ]), - titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ) + titreDemarchePublicFind(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, demarcheTypeId, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-02')), { + demarcheDateDebut: toCaminoDate('2020-01-01'), + demarcheDateFin: toCaminoDate('2021-01-01'), + etapes: etapesBuild([ + { typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-01'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + { typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-02'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + { typeId: ETAPES_TYPES.desistementDuDemandeur, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-01-05'), isBrouillon: ETAPE_IS_NOT_BROUILLON }, + ]), + titreId: newTitreId('titreId'), + }) ).toMatchObject({ publicLecture: true }) } ) @@ -777,15 +618,13 @@ describe("publicité d'une démarche", () => { ])("une démarche d’un titre non énergétique dont l'étape la plus récente est %s est public", etapeTypeId => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), etapes: etapesBuild([{ typeId: etapeTypeId, isBrouillon: ETAPE_IS_NOT_BROUILLON }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: true }) }) @@ -793,9 +632,8 @@ describe("publicité d'une démarche", () => { test('la demarche d’une prolongation déposée d’un PRM en survie provisoire est public ', () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Prolongation1, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - id: newDemarcheId(), - typeId: DEMARCHES_TYPES_IDS.Prolongation1, demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: null, etapes: etapesBuild([ @@ -803,8 +641,7 @@ describe("publicité d'une démarche", () => { { typeId: ETAPES_TYPES.enregistrementDeLaDemande, isBrouillon: ETAPE_IS_NOT_BROUILLON }, ]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX + } ) ).toMatchObject({ publicLecture: true }) }) @@ -812,15 +649,13 @@ describe("publicité d'une démarche", () => { test('le titre WQaZgPfDcQw9tFliMgBIDH3Z ne doit pas être public', () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - typeId: DEMARCHES_TYPES_IDS.Octroi, demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2021-01-01'), - id: newDemarcheId(), etapes: etapesBuild([{ typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, isBrouillon: ETAPE_IS_NOT_BROUILLON }]), titreId: newTitreId('WQaZgPfDcQw9tFliMgBIDH3Z'), - }, - TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_GRANULATS_MARINS + } ) ).toMatchObject({ publicLecture: false }) }) @@ -828,15 +663,13 @@ describe("publicité d'une démarche", () => { test('la demarche d’une prolongation non déposée d’un PRM en survie provisoire n’est pas public ', () => { expect( titreDemarchePublicFind( + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Prolongation1, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')), { - id: newDemarcheId(), - typeId: DEMARCHES_TYPES_IDS.Prolongation1, demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: null, etapes: etapesBuild([{ typeId: ETAPES_TYPES.demande, isBrouillon: ETAPE_IS_NOT_BROUILLON }]), titreId: newTitreId('titreId'), - }, - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX + } ) ).toMatchObject({ publicLecture: false }) }) diff --git a/packages/api/src/business/rules/titre-demarche-public-find.ts b/packages/api/src/business/rules/titre-demarche-public-find.ts index 95eeccb63..9630c8ac8 100644 --- a/packages/api/src/business/rules/titre-demarche-public-find.ts +++ b/packages/api/src/business/rules/titre-demarche-public-find.ts @@ -8,9 +8,9 @@ import { titreEtapesSortAscByOrdre } from '../utils/titre-etapes-sort' import { titreInModificationEnInstance } from './titre-statut-id-find' import { ETAPES_STATUTS, isEtapeStatusRejete } from 'camino-common/src/static/etapesStatuts' import { DOMAINES_IDS } from 'camino-common/src/static/domaines' -import { CaminoMachines, machineFind } from '../rules-demarches/machines' -import { demarcheEnregistrementDemandeDateFind } from 'camino-common/src/demarche' +import { ApiMachineInfo } from '../rules-demarches/machines' import { isNotNullNorUndefined } from 'camino-common/src/typescript-tools' +import { MachineInfo } from 'camino-common/src/machines' const titreDemarchePublicLectureFind = ( publicLecture: boolean, demarcheTypeId: DemarcheTypeId, @@ -197,8 +197,8 @@ const titreDemarchePublicLectureFind = ( */ export const titreDemarchePublicFind = ( - titreDemarche: Pick<ITitreDemarche, 'titreId' | 'demarcheDateDebut' | 'demarcheDateFin' | 'id' | 'typeId' | 'etapes'>, - titreTypeId: TitreTypeId + machineInfo: MachineInfo, + titreDemarche: Pick<ITitreDemarche, 'titreId' | 'demarcheDateDebut' | 'demarcheDateFin' | 'etapes'> ): { publicLecture: boolean; entreprisesLecture: boolean } => { const titreDemarcheEtapes = titreEtapesSortAscByOrdre(titreDemarche.etapes ?? []) @@ -210,19 +210,14 @@ export const titreDemarchePublicFind = ( if (titreDemarche.titreId === 'WQaZgPfDcQw9tFliMgBIDH3Z') { publicLecture = false } else { - const firstEtapeDate = demarcheEnregistrementDemandeDateFind(titreDemarcheEtapes) + const machine = new ApiMachineInfo(machineInfo) - let machine: CaminoMachines | undefined - if (isNotNullNorUndefined(firstEtapeDate)) { - machine = machineFind(titreTypeId, titreDemarche.typeId, titreDemarche.id, firstEtapeDate) - } - - if (isNotNullNorUndefined(machine)) { - publicLecture = machine.demarcheStatut(toMachineEtapes(titreDemarcheEtapes.map(etape => titreEtapeForMachineValidator.parse(etape)))).publique + if (isNotNullNorUndefined(machine.machine)) { + publicLecture = machine.machine.demarcheStatut(toMachineEtapes(titreDemarcheEtapes.map(etape => titreEtapeForMachineValidator.parse(etape)))).publique } else { - const demarcheTypeEtapesTypes = getEtapesTDE(titreTypeId, titreDemarche.typeId) + const demarcheTypeEtapesTypes = getEtapesTDE(machineInfo.titreTypeId, machineInfo.demarcheTypeId) publicLecture = titreDemarcheEtapes.reduce( - (publicLecture, titreEtape) => titreDemarchePublicLectureFind(publicLecture, titreDemarche.typeId, demarcheTypeEtapesTypes, titreEtape, titreDemarche, titreTypeId), + (publicLecture, titreEtape) => titreDemarchePublicLectureFind(publicLecture, machineInfo.demarcheTypeId, demarcheTypeEtapesTypes, titreEtape, titreDemarche, machineInfo.titreTypeId), false ) if (!publicLecture && titreDemarcheEtapes.length === 1 && titreDemarcheEtapes[0].typeId === ETAPES_TYPES.publicationDeDecisionAuJORF && titreDemarcheEtapes[0].statutId === ETAPES_STATUTS.FAIT) { diff --git a/packages/api/src/business/rules/titre-demarche-statut-id-find.test.ts b/packages/api/src/business/rules/titre-demarche-statut-id-find.test.ts index d59e0d596..108fd556d 100644 --- a/packages/api/src/business/rules/titre-demarche-statut-id-find.test.ts +++ b/packages/api/src/business/rules/titre-demarche-statut-id-find.test.ts @@ -11,6 +11,8 @@ import { ETAPE_IS_BROUILLON, ETAPE_IS_NOT_BROUILLON } from 'camino-common/src/et import { ETAPES_TYPES, EtapeTypeId } from 'camino-common/src/static/etapesTypes' import { TITRES_TYPES_IDS, TitreTypeId } from 'camino-common/src/static/titresTypes' import { DEMARCHES_TYPES_IDS, DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' +import { throwableMachineInfoForTestsOnly } from '../../../tests/_utils' + const etapesBuild = ( etapesProps: Partial<ITitreEtape>[], demarcheTypeId: DemarcheTypeId = DEMARCHES_TYPES_IDS.Octroi, @@ -30,16 +32,16 @@ const etapesBuild = ( describe("statut d'une démarche", () => { test('une démarche sans étape a le statut “indéfini”', () => { - expect(titreDemarcheStatutIdFind(DEMARCHES_TYPES_IDS.Octroi, [], TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, newDemarcheId())).toEqual(DemarchesStatutsIds.Indetermine) + expect(titreDemarcheStatutIdFind(throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), [])).toEqual( + DemarchesStatutsIds.Indetermine + ) }) test("une démarche d'octroi sans étape décisive a le statut “indéfini”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, - etapesBuild([{ typeId: ETAPES_TYPES.avisDeMiseEnConcurrenceAuJORF }], DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX), - TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, - newDemarcheId() + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.avisDeMiseEnConcurrenceAuJORF }], DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX) ) ).toEqual(DemarchesStatutsIds.Indetermine) }) @@ -47,7 +49,7 @@ describe("statut d'une démarche", () => { test("une démarche d'octroi dont l'étape de dpu la plus récente est acceptée a le statut “accepté”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), etapesBuild( [ { typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: ETAPES_STATUTS.ACCEPTE }, @@ -55,9 +57,7 @@ describe("statut d'une démarche", () => { ], DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX - ), - TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, - newDemarcheId() + ) ) ).toEqual(DemarchesStatutsIds.Accepte) }) @@ -65,14 +65,12 @@ describe("statut d'une démarche", () => { test("une démarche d'octroi d'un titre AXM dont l'étape de dex la plus récente est acceptée a le statut “accepté”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), etapesBuild( [{ typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, date: toCaminoDate('2010-01-01'), statutId: ETAPES_STATUTS.ACCEPTE }], DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX - ), - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, - newDemarcheId() + ) ) ).toEqual(DemarchesStatutsIds.Accepte) }) @@ -80,16 +78,14 @@ describe("statut d'une démarche", () => { test("une démarche d'octroi d'un titre ARM dont l'étape de def la plus récente est acceptée a le statut “accepté”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), etapesBuild([ { typeId: ETAPES_TYPES.decisionDeLOfficeNationalDesForets, statutId: ETAPES_STATUTS.ACCEPTE, date: toCaminoDate('2010-01-01'), }, - ]), - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - newDemarcheId() + ]) ) ).toEqual(DemarchesStatutsIds.Accepte) }) @@ -97,14 +93,12 @@ describe("statut d'une démarche", () => { test("une démarche d'octroi d'un titre PRM dont l'étape de rpu la plus récente est acceptée a le statut “accepté”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), etapesBuild( [{ typeId: ETAPES_TYPES.publicationDeDecisionAuRecueilDesActesAdministratifs, date: toCaminoDate('2010-01-01'), statutId: ETAPES_STATUTS.ACCEPTE }], DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX - ), - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, - newDemarcheId() + ) ) ).toEqual(DemarchesStatutsIds.Accepte) }) @@ -112,13 +106,11 @@ describe("statut d'une démarche", () => { test("une démarche de prolongation dont l'étape de dpu la plus récente est acceptée a le statut “accepté”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Prolongation, + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Prolongation, newDemarcheId(), null), etapesBuild([ { typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: ETAPES_STATUTS.ACCEPTE }, { typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: ETAPES_STATUTS.ACCEPTE }, - ]), - TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, - newDemarcheId() + ]) ) ).toEqual(DemarchesStatutsIds.Accepte) }) @@ -126,7 +118,7 @@ describe("statut d'une démarche", () => { test("une démarche d'octroi dont l'étape de sco est faite a le statut “accepté”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), etapesBuild([ { typeId: ETAPES_TYPES.demande, @@ -153,23 +145,19 @@ describe("statut d'une démarche", () => { { typeId: ETAPES_TYPES.paiementDesFraisDeDossierComplementaires, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-07-16') }, { typeId: ETAPES_TYPES.validationDuPaiementDesFraisDeDossierComplementaires, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-07-17') }, { typeId: ETAPES_TYPES.signatureDeLautorisationDeRechercheMiniere, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2020-09-28') }, - ]), - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - newDemarcheId() + ]) ) ).toEqual(DemarchesStatutsIds.Accepte) expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), etapesBuild([ { typeId: ETAPES_TYPES.signatureDeLautorisationDeRechercheMiniere, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2010-09-28'), }, - ]), - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - newDemarcheId() + ]) ) ).toEqual(DemarchesStatutsIds.Accepte) }) @@ -177,10 +165,8 @@ describe("statut d'une démarche", () => { test("une démarche d'octroi d'un titre autre qu'ARM dont l'étape de sco est faite a le statut “indéfini”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, - etapesBuild([{ typeId: ETAPES_TYPES.signatureDeLautorisationDeRechercheMiniere, statutId: ETAPES_STATUTS.FAIT }]), - TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, - newDemarcheId() + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.signatureDeLautorisationDeRechercheMiniere, statutId: ETAPES_STATUTS.FAIT }]) ) ).toEqual(DemarchesStatutsIds.Indetermine) }) @@ -188,10 +174,8 @@ describe("statut d'une démarche", () => { test("une démarche d'octroi ne contenant une unique étape de dex acceptée a le statut “en instruction”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, - etapesBuild([{ typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: ETAPES_STATUTS.ACCEPTE }]), - TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, - newDemarcheId() + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: ETAPES_STATUTS.ACCEPTE }]) ) ).toEqual(DemarchesStatutsIds.EnInstruction) }) @@ -199,13 +183,11 @@ describe("statut d'une démarche", () => { test("une démarche d'octroi contenant une étape de publication acceptée après une dex acceptée a le statut “accepté”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), etapesBuild([ { typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: ETAPES_STATUTS.ACCEPTE }, { typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: ETAPES_STATUTS.ACCEPTE }, - ]), - TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, - newDemarcheId() + ]) ) ).toEqual(DemarchesStatutsIds.Accepte) }) @@ -213,24 +195,25 @@ describe("statut d'une démarche", () => { test("une démarche d'octroi dont l'unique étape de dex est rejetée a le statut “rejeté”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, - etapesBuild([{ typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: ETAPES_STATUTS.REJETE }]), - TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, - newDemarcheId() + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: ETAPES_STATUTS.REJETE }]) ) ).toEqual(DemarchesStatutsIds.Rejete) }) test("une démarche d'octroi dont l'étape est men a le statut “déposé”", () => { expect( - titreDemarcheStatutIdFind(DEMARCHES_TYPES_IDS.Octroi, etapesBuild([{ typeId: ETAPES_TYPES.enregistrementDeLaDemande }]), TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, newDemarcheId()) + titreDemarcheStatutIdFind( + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.enregistrementDeLaDemande }]) + ) ).toEqual(DemarchesStatutsIds.Depose) }) test("une démarche d'octroi d'un titre ARM dont l'étape de men (statut fai) a le statut “en instruction”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), etapesBuild( [ { typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT }, @@ -238,9 +221,7 @@ describe("statut d'une démarche", () => { ], DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX - ), - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - newDemarcheId() + ) ) ).toEqual(DemarchesStatutsIds.EnInstruction) }) @@ -248,15 +229,13 @@ describe("statut d'une démarche", () => { test("une démarche d'octroi d'un titre ARM dont l'étape de mcp a le statut “en instruction”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), etapesBuild([ { typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT }, { typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: ETAPES_STATUTS.FAIT }, { typeId: ETAPES_TYPES.paiementDesFraisDeDossier, statutId: ETAPES_STATUTS.FAIT }, { typeId: ETAPES_TYPES.completudeDeLaDemande, statutId: ETAPES_STATUTS.COMPLETE }, - ]), - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - newDemarcheId() + ]) ) ).toEqual(DemarchesStatutsIds.EnInstruction) }) @@ -264,16 +243,14 @@ describe("statut d'une démarche", () => { test("une démarche d'octroi d'un titre ARM dont la dernière étape de def est acceptée a le statut “accepté”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), etapesBuild([ { typeId: ETAPES_TYPES.decisionDeLOfficeNationalDesForets, statutId: ETAPES_STATUTS.ACCEPTE, date: toCaminoDate('2010-01-01'), }, - ]), - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - newDemarcheId() + ]) ) ).toEqual(DemarchesStatutsIds.Accepte) }) @@ -281,16 +258,14 @@ describe("statut d'une démarche", () => { test("une démarche d'octroi d'un titre ARM dont la dernière étape de def est rejetée a le statut “rejeté”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), etapesBuild([ { typeId: ETAPES_TYPES.decisionDeLOfficeNationalDesForets, statutId: ETAPES_STATUTS.REJETE, date: toCaminoDate('2010-01-12'), }, - ]), - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - newDemarcheId() + ]) ) ).toEqual(DemarchesStatutsIds.Rejete) }) @@ -298,47 +273,52 @@ describe("statut d'une démarche", () => { test("une démarche d'octroi d'un titre autre qu'ARM dont la dernière étape est une def a le statut “indéfini”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, - etapesBuild([{ typeId: ETAPES_TYPES.decisionDeLOfficeNationalDesForets, statutId: ETAPES_STATUTS.REJETE }]), - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_HYDROCARBURE, - newDemarcheId() + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_HYDROCARBURE, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.decisionDeLOfficeNationalDesForets, statutId: ETAPES_STATUTS.REJETE }]) ) ).toEqual(DemarchesStatutsIds.Indetermine) }) test("une démarche d'octroi dont l'étape la plus récente est des a le statut “désisté”", () => { expect( - titreDemarcheStatutIdFind(DEMARCHES_TYPES_IDS.Octroi, etapesBuild([{ typeId: ETAPES_TYPES.desistementDuDemandeur }]), TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, newDemarcheId()) + titreDemarcheStatutIdFind( + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.desistementDuDemandeur }]) + ) ).toEqual(DemarchesStatutsIds.Desiste) }) test("une démarche d'octroi dont l'étape la plus récente est mfr a le statut “en construction”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, - etapesBuild([{ typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT, isBrouillon: ETAPE_IS_BROUILLON }]), - TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, - newDemarcheId() + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT, isBrouillon: ETAPE_IS_BROUILLON }]) ) ).toEqual(DemarchesStatutsIds.EnConstruction) }) test("une démarche d'octroi dont l'étape la plus récente est mcr a le statut “en instruction”", () => { expect( - titreDemarcheStatutIdFind(DEMARCHES_TYPES_IDS.Octroi, etapesBuild([{ typeId: ETAPES_TYPES.recevabiliteDeLaDemande }]), TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, newDemarcheId()) + titreDemarcheStatutIdFind( + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.recevabiliteDeLaDemande }]) + ) ).toEqual(DemarchesStatutsIds.EnInstruction) }) test("une démarche d'octroi dont l'étape la plus récente est css a le statut “classé sans suite”", () => { - expect(titreDemarcheStatutIdFind(DEMARCHES_TYPES_IDS.Octroi, etapesBuild([{ typeId: ETAPES_TYPES.classementSansSuite }]), TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, newDemarcheId())).toEqual( - DemarchesStatutsIds.ClasseSansSuite - ) + expect( + titreDemarcheStatutIdFind( + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.classementSansSuite }]) + ) + ).toEqual(DemarchesStatutsIds.ClasseSansSuite) }) test("une démarche d'octroi dont l'étape la plus récente d'aca est défavorable a le statut “rejeté”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), etapesBuild([ { typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2021-02-25') }, { typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2021-02-26') }, @@ -349,9 +329,7 @@ describe("statut d'une démarche", () => { { typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2021-09-23') }, { typeId: ETAPES_TYPES.saisineDeLaCommissionDesAutorisationsDeRecherchesMinieres_CARM_, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2021-09-24') }, { typeId: ETAPES_TYPES.avisDeLaCommissionDesAutorisationsDeRecherchesMinieres_CARM_, statutId: ETAPES_STATUTS.DEFAVORABLE, date: toCaminoDate('2021-09-25') }, - ]), - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - newDemarcheId() + ]) ) ).toEqual(DemarchesStatutsIds.Rejete) }) @@ -359,7 +337,7 @@ describe("statut d'une démarche", () => { test("une démarche d'octroi dont l'étape la plus récente d'aca est favorable reste “en instruction”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), etapesBuild([ { typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2021-02-25') }, { typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2021-02-26') }, @@ -370,43 +348,43 @@ describe("statut d'une démarche", () => { { typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2021-09-23') }, { typeId: ETAPES_TYPES.saisineDeLaCommissionDesAutorisationsDeRecherchesMinieres_CARM_, statutId: ETAPES_STATUTS.FAIT, date: toCaminoDate('2021-09-24') }, { typeId: ETAPES_TYPES.avisDeLaCommissionDesAutorisationsDeRecherchesMinieres_CARM_, statutId: ETAPES_STATUTS.FAVORABLE, date: toCaminoDate('2021-09-25') }, - ]), - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - newDemarcheId() + ]) ) ).toEqual(DemarchesStatutsIds.EnInstruction) }) test('une démarche de retrait sans aucune étape décisive a le statut “indéterminé”', () => { expect( - titreDemarcheStatutIdFind(DEMARCHES_TYPES_IDS.Retrait, etapesBuild([{ typeId: ETAPES_TYPES.informationsHistoriquesIncompletes }]), TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, newDemarcheId()) + titreDemarcheStatutIdFind( + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Retrait, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.informationsHistoriquesIncompletes }]) + ) ).toEqual(DemarchesStatutsIds.Indetermine) }) test("une démarche de retrait dont l'étape la plus récente de dpu a été faite a le statut “terminé”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Retrait, - etapesBuild([{ typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: ETAPES_STATUTS.FAIT }]), - TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, - newDemarcheId() + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Retrait, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: ETAPES_STATUTS.FAIT }]) ) ).toEqual(DemarchesStatutsIds.Termine) }) test("une démarche de retrait dont l'étape la plus récente est spp a le statut “en instruction”", () => { - expect(titreDemarcheStatutIdFind(DEMARCHES_TYPES_IDS.Retrait, etapesBuild([{ typeId: ETAPES_TYPES.saisineDuPrefet }]), TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, newDemarcheId())).toEqual( - DemarchesStatutsIds.EnInstruction - ) + expect( + titreDemarcheStatutIdFind( + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Retrait, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.saisineDuPrefet }]) + ) + ).toEqual(DemarchesStatutsIds.EnInstruction) }) test("une démarche de retrait dont l'étape la plus récente est asc a le statut “en instruction”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Retrait, - etapesBuild([{ typeId: ETAPES_TYPES.saisineDuPrefet }, { typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives }]), - TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, - newDemarcheId() + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Retrait, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.saisineDuPrefet }, { typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives }]) ) ).toEqual(DemarchesStatutsIds.EnInstruction) }) @@ -414,39 +392,44 @@ describe("statut d'une démarche", () => { test("une démarche de retrait dont l'étape la plus récente est aco a le statut “terminé”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Retrait, - etapesBuild([{ typeId: ETAPES_TYPES.avenantALautorisationDeRechercheMiniere }]), - TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, - newDemarcheId() + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Retrait, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.avenantALautorisationDeRechercheMiniere }]) ) ).toEqual(DemarchesStatutsIds.Termine) }) test("une démarche de retrait dont l'étape la plus récente de css a été faite a le statut “classé sans suite”", () => { - expect(titreDemarcheStatutIdFind(DEMARCHES_TYPES_IDS.Retrait, etapesBuild([{ typeId: ETAPES_TYPES.classementSansSuite }]), TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, newDemarcheId())).toEqual( - DemarchesStatutsIds.ClasseSansSuite - ) + expect( + titreDemarcheStatutIdFind( + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Retrait, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.classementSansSuite }]) + ) + ).toEqual(DemarchesStatutsIds.ClasseSansSuite) }) test("une démarche de demande dont l'étape la plus récente est spp ne change pas de statut", () => { - expect(titreDemarcheStatutIdFind(DEMARCHES_TYPES_IDS.Octroi, etapesBuild([{ typeId: ETAPES_TYPES.saisineDuPrefet }]), TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, newDemarcheId())).toEqual( - DemarchesStatutsIds.Indetermine - ) + expect( + titreDemarcheStatutIdFind( + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.saisineDuPrefet }]) + ) + ).toEqual(DemarchesStatutsIds.Indetermine) }) test("une démarche dont l'étape la plus récente est de type “abrogation de la décision” a le statut “en instruction”", () => { expect( - titreDemarcheStatutIdFind(DEMARCHES_TYPES_IDS.Octroi, etapesBuild([{ typeId: ETAPES_TYPES.abrogationDeLaDecision }]), TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, newDemarcheId()) + titreDemarcheStatutIdFind( + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.abrogationDeLaDecision }]) + ) ).toEqual(DemarchesStatutsIds.EnInstruction) }) test("une démarche dont l'étape la plus récente d'annulation de la décision est favorable a le statut “en instruction”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, - etapesBuild([{ typeId: ETAPES_TYPES.decisionDuJugeAdministratif, statutId: ETAPES_STATUTS.FAIT }]), - TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, - newDemarcheId() + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.decisionDuJugeAdministratif, statutId: ETAPES_STATUTS.FAIT }]) ) ).toEqual(DemarchesStatutsIds.EnInstruction) }) @@ -454,10 +437,8 @@ describe("statut d'une démarche", () => { test("une démarche dont l'étape la plus récente d'annulation de la décision est favorable a le statut “accepté”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, - etapesBuild([{ typeId: ETAPES_TYPES.decisionDuJugeAdministratif, statutId: ETAPES_STATUTS.ACCEPTE }]), - TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, - newDemarcheId() + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.decisionDuJugeAdministratif, statutId: ETAPES_STATUTS.ACCEPTE }]) ) ).toEqual(DemarchesStatutsIds.Accepte) }) @@ -465,10 +446,8 @@ describe("statut d'une démarche", () => { test("une démarche dont l'étape la plus récente d'annulation de la décision est favorable a le statut “rejeté”", () => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.Octroi, - etapesBuild([{ typeId: ETAPES_TYPES.decisionDuJugeAdministratif, statutId: ETAPES_STATUTS.REJETE }]), - TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, - newDemarcheId() + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.decisionDuJugeAdministratif, statutId: ETAPES_STATUTS.REJETE }]) ) ).toEqual(DemarchesStatutsIds.Rejete) }) @@ -477,10 +456,8 @@ describe("statut d'une démarche", () => { expect( titreDemarcheStatutIdFind( // @ts-ignore - 'xxx', - etapesBuild([{ typeId: ETAPES_TYPES.demande }]), - TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, - newDemarcheId() + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, 'xxx', newDemarcheId(), null), + etapesBuild([{ typeId: ETAPES_TYPES.demande }]) ) ).toEqual(DemarchesStatutsIds.Indetermine) }) @@ -504,7 +481,10 @@ describe("statut d'une démarche", () => { [Travaux.DesistementDuDemandeur, ETAPES_STATUTS.FAIT, Demarches.Desiste], ])("pour une démarche de travaux de type 'AutorisationDOuvertureDeTravaux' sur un titre, dont la dernière étape est '%s' au statut %s, le résultat est %s", (etapeTypeId, statutId, resultId) => { expect( - titreDemarcheStatutIdFind(DEMARCHES_TYPES_IDS.AutorisationDOuvertureDeTravaux, etapesBuild([{ typeId: etapeTypeId, statutId }]), TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, newDemarcheId()) + titreDemarcheStatutIdFind( + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.AutorisationDOuvertureDeTravaux, newDemarcheId(), null), + etapesBuild([{ typeId: etapeTypeId, statutId }]) + ) ).toEqual(resultId) }) @@ -523,7 +503,10 @@ describe("statut d'une démarche", () => { [Travaux.DesistementDuDemandeur, ETAPES_STATUTS.FAIT, Demarches.Desiste], ])("pour une démarche de travaux de type 'DeclarationDOuvertureDeTravaux' sur un titre, dont la dernière étape est '%s' au statut %s, le résultat est %s", (etapeTypeId, statutId, resultId) => { expect( - titreDemarcheStatutIdFind(DEMARCHES_TYPES_IDS.DeclarationDOuvertureDeTravaux, etapesBuild([{ typeId: etapeTypeId, statutId }]), TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, newDemarcheId()) + titreDemarcheStatutIdFind( + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.DeclarationDOuvertureDeTravaux, newDemarcheId(), null), + etapesBuild([{ typeId: etapeTypeId, statutId }]) + ) ).toEqual(resultId) }) @@ -550,10 +533,8 @@ describe("statut d'une démarche", () => { (etapeTypeId, statutId, resultId) => { expect( titreDemarcheStatutIdFind( - DEMARCHES_TYPES_IDS.DeclarationDArretDefinitifDesTravaux, - etapesBuild([{ typeId: etapeTypeId, statutId }]), - TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, - newDemarcheId() + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.DeclarationDArretDefinitifDesTravaux, newDemarcheId(), null), + etapesBuild([{ typeId: etapeTypeId, statutId }]) ) ).toEqual(resultId) } diff --git a/packages/api/src/business/rules/titre-demarche-statut-id-find.ts b/packages/api/src/business/rules/titre-demarche-statut-id-find.ts index d3fe4ce2a..1ae0b2a17 100644 --- a/packages/api/src/business/rules/titre-demarche-statut-id-find.ts +++ b/packages/api/src/business/rules/titre-demarche-statut-id-find.ts @@ -1,5 +1,4 @@ import { ITitreEtape, TitreEtapesTravauxTypes as Travaux } from '../../types' -import { demarcheEnregistrementDemandeDateFind, DemarcheId } from 'camino-common/src/demarche' import { titreEtapesSortDescByOrdre } from '../utils/titre-etapes-sort' import { titreEtapePublicationCheck } from './titre-etape-publication-check' @@ -10,7 +9,8 @@ import { DemarcheTypeId, TravauxIds } from 'camino-common/src/static/demarchesTy import { ETAPES_TYPES, EtapeTypeId } from 'camino-common/src/static/etapesTypes' import { ETAPES_STATUTS, isEtapeStatusRejete } from 'camino-common/src/static/etapesStatuts' import { exhaustiveCheck, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, RecordPartial } from 'camino-common/src/typescript-tools' -import { machineFind } from '../rules-demarches/machines' +import { MachineInfo } from 'camino-common/src/machines' +import { ApiMachineInfo } from '../rules-demarches/machines' const titreEtapesDecisivesCommunesTypes = ['css', 'abd', 'and'] as const satisfies EtapeTypeId[] @@ -318,29 +318,20 @@ const titreDemarcheTravauxStatutIdFind = (titreDemarcheEtapes: Pick<ITitreEtape, return statuts[titreEtapesRecent.typeId] ?? DemarchesStatutsIds.Indetermine } -/** - * Retourne l'id du statut d'une démarche - * @param demarcheTypeId - id du type de la démarche - * @param titreDemarcheEtapes - étapes de la démarche - * @param titreTypeId - id du type de titre - */ - -export const titreDemarcheStatutIdFind = (demarcheTypeId: DemarcheTypeId, titreDemarcheEtapes: TitreEtapeForMachine[], titreTypeId: TitreTypeId, demarcheId: DemarcheId): DemarcheStatutId => { +export const titreDemarcheStatutIdFind = (machineInfo: MachineInfo, titreDemarcheEtapes: TitreEtapeForMachine[]): DemarcheStatutId => { // si la démarche ne contient pas d'étapes // -> le statut est indétrminé if (!isNotNullNorUndefinedNorEmpty(titreDemarcheEtapes)) return DemarchesStatutsIds.Indetermine // si la démarche est pour des travaux - if (titreDemarchesTravauxTypes.includes(demarcheTypeId)) { - return titreDemarcheTravauxStatutIdFind(titreDemarcheEtapes, demarcheTypeId) + if (titreDemarchesTravauxTypes.includes(machineInfo.demarcheTypeId)) { + return titreDemarcheTravauxStatutIdFind(titreDemarcheEtapes, machineInfo.demarcheTypeId) } - const firstEtapeDate = demarcheEnregistrementDemandeDateFind(titreDemarcheEtapes) - - const machine = machineFind(titreTypeId, demarcheTypeId, demarcheId, firstEtapeDate) + const machine = new ApiMachineInfo(machineInfo) - if (isNotNullNorUndefined(machine)) { - return machine.demarcheStatut(toMachineEtapes(titreDemarcheEtapes)).demarcheStatut + if (isNotNullNorUndefined(machine.machine)) { + return machine.machine.demarcheStatut(toMachineEtapes(titreDemarcheEtapes)).demarcheStatut } // si la démarche fait l’objet d’une demande @@ -349,13 +340,13 @@ export const titreDemarcheStatutIdFind = (demarcheTypeId: DemarcheTypeId, titreD // - renonciation ou fusion (native ou virtuelle) ou extension du périmètre // - extension de substance ou mutation (native ou virtuelle) ou amodiation // - résiliation d’amodiation ou déplacement de périmètre) - if (titreDemarchesDemandesTypes.includes(demarcheTypeId)) { - return titreDemarcheDemandeStatutIdFind(titreDemarcheEtapes, titreTypeId) + if (titreDemarchesDemandesTypes.includes(machineInfo.demarcheTypeId)) { + return titreDemarcheDemandeStatutIdFind(titreDemarcheEtapes, machineInfo.titreTypeId) } // si la démarche ne fait pas l’objet d’une demande (unilatérale) // (son type est retrait ou abrogation ou prorogation) - else if (titreDemarchesUnilateralesTypes.includes(demarcheTypeId)) { + else if (titreDemarchesUnilateralesTypes.includes(machineInfo.demarcheTypeId)) { return titreDemarcheUnilateralStatutIdFind(titreDemarcheEtapes) } diff --git a/packages/api/src/business/rules/titre-etape-prop-find.test.ts b/packages/api/src/business/rules/titre-etape-prop-find.test.ts index 68295cf98..384386b5c 100644 --- a/packages/api/src/business/rules/titre-etape-prop-find.test.ts +++ b/packages/api/src/business/rules/titre-etape-prop-find.test.ts @@ -2,12 +2,16 @@ import { ITitreDemarche } from '../../types' import { titreEtapePropFind } from './titre-etape-prop-find' import { vi, describe, expect, test } from 'vitest' -import { toCaminoDate } from 'camino-common/src/date' +import { firstEtapeDateValidator, toCaminoDate } from 'camino-common/src/date' import { ETAPE_IS_NOT_BROUILLON, etapeIdValidator } from 'camino-common/src/etape' import { titreIdValidator } from 'camino-common/src/validators/titres' import { demarcheIdValidator } from 'camino-common/src/demarche' import { ZERO_KM2 } from 'camino-common/src/number' import { newEntrepriseId } from 'camino-common/src/entreprise' +import { MachineInfo } from 'camino-common/src/machines' +import { TITRES_TYPES_IDS } from 'camino-common/src/static/titresTypes' +import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes' +import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' console.error = vi.fn() describe("valeur d'une propriété pour une étape", () => { @@ -31,12 +35,13 @@ describe("valeur d'une propriété pour une étape", () => { { id: demarcheId, titreId: titreIdValidator.parse('titreId'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('1000-01-01')).machineId ?? null, etapes: [ { id: etapeIdValidator.parse('demarche-01-etape-01'), titreDemarcheId: demarcheId, - typeId: 'asc', + typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, statutId: 'fai', isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1000-01-01'), @@ -51,7 +56,7 @@ describe("valeur d'une propriété pour une étape", () => { { id: etapeIdValidator.parse('demarche-01-etape-02'), titreDemarcheId: demarcheId, - typeId: 'asc', + typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, statutId: 'fai', isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1000-01-01'), @@ -66,7 +71,7 @@ describe("valeur d'une propriété pour une étape", () => { ], }, ], - 'pxm' + TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX ) ).toEqual(['fr-xxxxxxxxx']) }) @@ -81,12 +86,15 @@ describe("valeur d'une propriété pour une étape", () => { id: demarcheIdValidator.parse('demarche-01'), titreId: titreIdValidator.parse('titreId'), statutId: 'acc', - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarche-01'), firstEtapeDateValidator.parse('1000-01-01')) + .machineId ?? null, etapes: [ { id: etapeIdValidator.parse('demarche-01-etape-01'), titreDemarcheId: demarcheIdValidator.parse('demarche-01'), - typeId: 'asc', + typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, statutId: 'fai', isBrouillon: ETAPE_IS_NOT_BROUILLON, surface: ZERO_KM2, @@ -103,13 +111,16 @@ describe("valeur d'une propriété pour une étape", () => { id: demarcheIdValidator.parse('demarche-02'), titreId: titreIdValidator.parse('titreId'), statutId: 'acc', - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarche-02'), firstEtapeDateValidator.parse('1000-01-01')) + .machineId ?? null, etapes: [ { id: etapeIdValidator.parse('demarche-02-etape-01'), titreDemarcheId: demarcheIdValidator.parse('demarche-02'), date: toCaminoDate('1000-01-01'), - typeId: 'asc', + typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, statutId: 'fai', isBrouillon: ETAPE_IS_NOT_BROUILLON, surface: ZERO_KM2, @@ -122,7 +133,7 @@ describe("valeur d'une propriété pour une étape", () => { ], }, ], - 'pxm' + TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX ) ).toEqual(0) }) @@ -136,7 +147,10 @@ describe("valeur d'une propriété pour une étape", () => { { id: demarcheIdValidator.parse('demarche-01'), titreId: titreIdValidator.parse('titreId'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarche-01'), firstEtapeDateValidator.parse('1000-01-01')) + .machineId ?? null, etapes: [ { id: etapeIdValidator.parse('demarche-02-etape-01'), @@ -145,7 +159,7 @@ describe("valeur d'une propriété pour une étape", () => { statutId: 'fai', isBrouillon: ETAPE_IS_NOT_BROUILLON, titulaireIds: null, - typeId: 'asc', + typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, surface: ZERO_KM2, ordre: 1, communes: null, @@ -156,7 +170,7 @@ describe("valeur d'une propriété pour une étape", () => { ], }, ], - 'pxm' + TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX ) ).toBeNull() }) diff --git a/packages/api/src/business/rules/titre-phases-find.test.ts b/packages/api/src/business/rules/titre-phases-find.test.ts index 564ccab51..7df228e69 100644 --- a/packages/api/src/business/rules/titre-phases-find.test.ts +++ b/packages/api/src/business/rules/titre-phases-find.test.ts @@ -3,17 +3,18 @@ import { demarcheSlugValidator } from 'camino-common/src/demarche' import { titrePhasesFind, TitreDemarchePhaseFind } from './titre-phases-find' import { newDemarcheId, newEtapeId, newTitreId } from '../../database/models/_format/id-create' -import { toCaminoDate } from 'camino-common/src/date' +import { firstEtapeDateValidator, toCaminoDate } from 'camino-common/src/date' import { describe, expect, test } from 'vitest' import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes' import { DemarchesStatutsIds } from 'camino-common/src/static/demarchesStatuts' -import { TitreTypeId } from 'camino-common/src/static/titresTypes' +import { TITRES_TYPES_IDS, TitreTypeId } from 'camino-common/src/static/titresTypes' import { ETAPES_STATUTS } from 'camino-common/src/static/etapesStatuts' import { ETAPE_IS_BROUILLON, ETAPE_IS_NOT_BROUILLON, etapeSlugValidator } from 'camino-common/src/etape' import { FeatureMultiPolygon } from 'camino-common/src/perimetre' import { km2Validator } from 'camino-common/src/number' import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' +import { MachineInfo } from 'camino-common/src/machines' export type TitrePhasesTest = [TitreTypeId, TitreDemarchePhaseFind[]] const multiPolygonWith4Points: FeatureMultiPolygon = { @@ -43,6 +44,9 @@ describe("phases d'une démarche", () => { titreId: newTitreId('titreid'), id: newDemarcheId('demarcheId'), typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_RADIOACTIF, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('demarcheId'), firstEtapeDateValidator.parse('2000-01-01')) + .machineId ?? null, statutId: DemarchesStatutsIds.Rejete, etapes: [ { @@ -68,7 +72,7 @@ describe("phases d'une démarche", () => { ], }, ], - 'prr' + TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_RADIOACTIF ) ).toEqual({}) }) @@ -80,11 +84,14 @@ describe("phases d'une démarche", () => { { titreId: newTitreId('titreid'), id: newDemarcheId('h-cx-courdemanges-1988-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('h-cx-courdemanges-1988-oct01'), firstEtapeDateValidator.parse('2000-01-01')) + .machineId ?? null, statutId: 'acc', etapes: [ { - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -94,7 +101,7 @@ describe("phases d'une démarche", () => { demarcheIdsConsentement: [], }, { - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -106,7 +113,7 @@ describe("phases d'une démarche", () => { ], }, ], - 'cxh' + TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE ) ).toEqual({ 'h-cx-courdemanges-1988-oct01': { @@ -123,12 +130,13 @@ describe("phases d'une démarche", () => { { titreId: newTitreId('titreId'), id: newDemarcheId('h-cx-courdemanges-1988-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: 'ProcedureSimplifiee', statutId: 'acc', etapes: [], }, ], - 'cxh' + TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE ) ).toEqual({}) }) @@ -140,11 +148,18 @@ describe("phases d'une démarche", () => { { titreId: newTitreId('titreId'), id: newDemarcheId('h-ax-courdemanges-1988-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate( + TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_GEOTHERMIE, + DEMARCHES_TYPES_IDS.Octroi, + newDemarcheId('h-ax-courdemanges-1988-oct01'), + firstEtapeDateValidator.parse('2200-01-01') + ).machineId ?? null, statutId: 'acc', etapes: [ { - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -156,7 +171,7 @@ describe("phases d'une démarche", () => { ], }, ], - 'pxg' + TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_GEOTHERMIE ) ).toEqual({ 'h-ax-courdemanges-1988-oct01': { @@ -173,11 +188,18 @@ describe("phases d'une démarche", () => { { titreId: newTitreId('titreId'), id: newDemarcheId('m-pr-courdemanges-1988-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate( + TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, + DEMARCHES_TYPES_IDS.Octroi, + newDemarcheId('m-pr-courdemanges-1988-oct01'), + firstEtapeDateValidator.parse('1999-01-01') + ).machineId ?? null, statutId: 'acc', etapes: [ { - typeId: 'rpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuRecueilDesActesAdministratifs, statutId: 'fai', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -189,7 +211,7 @@ describe("phases d'une démarche", () => { ], }, ], - 'prm' + TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX ) ).toEqual({ 'm-pr-courdemanges-1988-oct01': { @@ -206,11 +228,14 @@ describe("phases d'une démarche", () => { { titreId: newTitreId('titreId'), id: newDemarcheId('h-cx-courdemanges-1988-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('h-cx-courdemanges-1988-oct01'), firstEtapeDateValidator.parse('2200-01-01')) + .machineId ?? null, statutId: 'acc', etapes: [ { - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -221,7 +246,7 @@ describe("phases d'une démarche", () => { demarcheIdsConsentement: [], }, { - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -234,7 +259,7 @@ describe("phases d'une démarche", () => { ], }, ], - 'cxh' + TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE ) ).toEqual({ 'h-cx-courdemanges-1988-oct01': { @@ -251,14 +276,17 @@ describe("phases d'une démarche", () => { { titreId: newTitreId('titreId'), id: newDemarcheId('h-cx-courdemanges-1988-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('h-cx-courdemanges-1988-oct01'), firstEtapeDateValidator.parse('2200-01-01')) + .machineId ?? null, statutId: 'acc', ordre: 1, etapes: [ { titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'), demarcheIdsConsentement: [], - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -268,7 +296,7 @@ describe("phases d'une démarche", () => { { titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'), demarcheIdsConsentement: [], - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -280,14 +308,21 @@ describe("phases d'une démarche", () => { { titreId: newTitreId('titreId'), id: newDemarcheId('h-cx-courdemanges-1988-pro01'), - typeId: 'pro', + typeId: DEMARCHES_TYPES_IDS.Prolongation, + machineId: + MachineInfo.withDate( + TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE, + DEMARCHES_TYPES_IDS.Prolongation, + newDemarcheId('h-cx-courdemanges-1988-pro01'), + firstEtapeDateValidator.parse('2300-01-01') + ).machineId ?? null, statutId: 'acc', ordre: 2, etapes: [ { titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-pro01'), demarcheIdsConsentement: [], - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -297,7 +332,7 @@ describe("phases d'une démarche", () => { { titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-pro01'), demarcheIdsConsentement: [], - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -307,7 +342,7 @@ describe("phases d'une démarche", () => { ], }, ], - 'cxh' + TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE ) ).toEqual({ 'h-cx-courdemanges-1988-oct01': { @@ -328,14 +363,17 @@ describe("phases d'une démarche", () => { { titreId: newTitreId('titreId'), id: newDemarcheId('h-cx-courdemanges-1988-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('h-cx-courdemanges-1988-oct01'), firstEtapeDateValidator.parse('2000-01-01')) + .machineId ?? null, statutId: 'acc', ordre: 1, etapes: [ { titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'), demarcheIdsConsentement: [], - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -345,7 +383,7 @@ describe("phases d'une démarche", () => { { titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'), demarcheIdsConsentement: [], - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -357,14 +395,21 @@ describe("phases d'une démarche", () => { { titreId: newTitreId('titreId'), id: newDemarcheId('h-cx-courdemanges-1988-ren01'), - typeId: 'rec', + typeId: DEMARCHES_TYPES_IDS.RenonciationTotale, + machineId: + MachineInfo.withDate( + TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE, + DEMARCHES_TYPES_IDS.RenonciationTotale, + newDemarcheId('h-cx-courdemanges-1988-ren01'), + firstEtapeDateValidator.parse('2019-01-02') + ).machineId ?? null, statutId: 'acc', ordre: 2, etapes: [ { titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-ren01'), demarcheIdsConsentement: [], - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -373,7 +418,7 @@ describe("phases d'une démarche", () => { { titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-ren01'), demarcheIdsConsentement: [], - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'fai', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -382,7 +427,7 @@ describe("phases d'une démarche", () => { ], }, ], - 'cxh' + TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE ) ).toEqual({ 'h-cx-courdemanges-1988-oct01': { @@ -399,14 +444,17 @@ describe("phases d'une démarche", () => { { titreId: newTitreId('titreId'), id: newDemarcheId('h-cx-courdemanges-1988-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('h-cx-courdemanges-1988-oct01'), firstEtapeDateValidator.parse('2000-01-01')) + .machineId ?? null, statutId: 'acc', ordre: 1, etapes: [ { titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'), demarcheIdsConsentement: [], - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -416,7 +464,7 @@ describe("phases d'une démarche", () => { { titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'), demarcheIdsConsentement: [], - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -428,14 +476,21 @@ describe("phases d'une démarche", () => { { titreId: newTitreId('titreId'), id: newDemarcheId('h-cx-courdemanges-1988-ren01'), - typeId: 'rep', + typeId: DEMARCHES_TYPES_IDS.RenonciationPartielle, + machineId: + MachineInfo.withDate( + TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE, + DEMARCHES_TYPES_IDS.RenonciationPartielle, + newDemarcheId('h-cx-courdemanges-1988-ren01'), + firstEtapeDateValidator.parse('2019-01-02') + ).machineId ?? null, statutId: 'acc', ordre: 2, etapes: [ { titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-ren01'), demarcheIdsConsentement: [], - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -444,7 +499,7 @@ describe("phases d'une démarche", () => { { titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-ren01'), demarcheIdsConsentement: [], - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -454,7 +509,7 @@ describe("phases d'une démarche", () => { ], }, ], - 'cxh' + TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE ) ).toEqual({ 'h-cx-courdemanges-1988-oct01': { @@ -482,7 +537,8 @@ describe("phases d'une démarche", () => { titreId, id: demarcheId1, ordre: 11, - typeId: 'mut', + typeId: DEMARCHES_TYPES_IDS.Mutation, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.Mutation, demarcheId1, firstEtapeDateValidator.parse('2016-12-28')).machineId ?? null, statutId: 'cls', etapes: [ { @@ -493,7 +549,7 @@ describe("phases d'une démarche", () => { date: toCaminoDate('2016-12-28'), duree: 1920, surface: km2Validator.parse(5.51), - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, statutId: 'fai', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -505,7 +561,7 @@ describe("phases d'une démarche", () => { ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2016-12-28'), - typeId: 'men', + typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: 'fai', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -517,7 +573,7 @@ describe("phases d'une démarche", () => { ordre: 3, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2017-04-07'), - typeId: 'css', + typeId: ETAPES_TYPES.classementSansSuite, statutId: 'fai', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -529,7 +585,8 @@ describe("phases d'une démarche", () => { id: demarcheId2, titreId, ordre: 10, - typeId: 'pro', + typeId: DEMARCHES_TYPES_IDS.Prolongation, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.Prolongation, demarcheId2, firstEtapeDateValidator.parse('2016-12-28')).machineId ?? null, statutId: 'cls', etapes: [ { @@ -540,7 +597,7 @@ describe("phases d'une démarche", () => { date: toCaminoDate('2016-12-28'), duree: 1920, surface: km2Validator.parse(5.51), - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, statutId: 'fai', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -552,7 +609,7 @@ describe("phases d'une démarche", () => { ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2016-12-28'), - typeId: 'men', + typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: 'fai', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -564,7 +621,7 @@ describe("phases d'une démarche", () => { ordre: 3, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2017-04-07'), - typeId: 'css', + typeId: ETAPES_TYPES.classementSansSuite, statutId: 'fai', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -576,7 +633,10 @@ describe("phases d'une démarche", () => { titreId, id: demarcheId3, ordre: 9, - typeId: 'dam', + typeId: DEMARCHES_TYPES_IDS.DeclarationDArretDefinitifDesTravaux, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.DeclarationDArretDefinitifDesTravaux, demarcheId3, firstEtapeDateValidator.parse('2013-08-01')).machineId ?? + null, statutId: 'ins', etapes: [ { @@ -585,7 +645,7 @@ describe("phases d'une démarche", () => { ordre: 3, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2014-12-23'), - typeId: 'wpp', + typeId: ETAPES_TYPES.arretePrefectoralDePremierDonnerActe_DADT_, statutId: 'fai', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -597,7 +657,7 @@ describe("phases d'une démarche", () => { ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2013-08-01'), - typeId: 'wfd', + typeId: ETAPES_TYPES.declarationDarretDefinitifDeTravaux_DADT_, statutId: 'fai', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -621,7 +681,8 @@ describe("phases d'une démarche", () => { titreId, id: demarcheId4, ordre: 8, - typeId: 'mut', + typeId: DEMARCHES_TYPES_IDS.Mutation, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.Mutation, demarcheId4, firstEtapeDateValidator.parse('2002-12-24')).machineId ?? null, statutId: 'acc', etapes: [ { @@ -630,7 +691,7 @@ describe("phases d'une démarche", () => { ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2002-12-24'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -642,7 +703,7 @@ describe("phases d'une démarche", () => { ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2003-01-08'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -654,7 +715,8 @@ describe("phases d'une démarche", () => { titreId, id: demarcheId5, ordre: 7, - typeId: 'mut', + typeId: DEMARCHES_TYPES_IDS.Mutation, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.Mutation, demarcheId5, firstEtapeDateValidator.parse('2000-09-26')).machineId ?? null, statutId: 'acc', etapes: [ { @@ -663,7 +725,7 @@ describe("phases d'une démarche", () => { ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2000-09-26'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -675,7 +737,7 @@ describe("phases d'une démarche", () => { ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2000-10-06'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -687,7 +749,8 @@ describe("phases d'une démarche", () => { titreId, id: demarcheId6, ordre: 6, - typeId: 'mut', + typeId: DEMARCHES_TYPES_IDS.Mutation, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.Mutation, demarcheId6, firstEtapeDateValidator.parse('1975-11-24')).machineId ?? null, statutId: 'acc', etapes: [ { @@ -696,7 +759,7 @@ describe("phases d'une démarche", () => { ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1975-11-24'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -708,7 +771,7 @@ describe("phases d'une démarche", () => { ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1975-11-27'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -720,8 +783,8 @@ describe("phases d'une démarche", () => { titreId, id: demarcheId7, ordre: 5, - typeId: 'mut', - + typeId: DEMARCHES_TYPES_IDS.Mutation, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.Mutation, demarcheId7, firstEtapeDateValidator.parse('1970-11-16')).machineId ?? null, statutId: 'acc', etapes: [ { @@ -730,7 +793,7 @@ describe("phases d'une démarche", () => { ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1970-11-16'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -742,7 +805,7 @@ describe("phases d'une démarche", () => { ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1970-11-19'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -754,7 +817,8 @@ describe("phases d'une démarche", () => { titreId, id: demarcheId8, ordre: 4, - typeId: 'mut', + typeId: DEMARCHES_TYPES_IDS.Mutation, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.Mutation, demarcheId8, firstEtapeDateValidator.parse('1949-08-23')).machineId ?? null, statutId: 'acc', etapes: [ { @@ -763,7 +827,7 @@ describe("phases d'une démarche", () => { ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1949-08-31'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -775,7 +839,7 @@ describe("phases d'une démarche", () => { ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1949-08-23'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -787,7 +851,8 @@ describe("phases d'une démarche", () => { titreId, id: demarcheId9, ordre: 3, - typeId: 'exp', + typeId: DEMARCHES_TYPES_IDS.ExtensionDePerimetre, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.ExtensionDePerimetre, demarcheId9, firstEtapeDateValidator.parse('1889-02-27')).machineId ?? null, statutId: 'acc', etapes: [ { @@ -796,7 +861,7 @@ describe("phases d'une démarche", () => { ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1889-02-27'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -808,7 +873,7 @@ describe("phases d'une démarche", () => { ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1889-02-27'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -820,7 +885,8 @@ describe("phases d'une démarche", () => { titreId, id: demarcheId10, ordre: 2, - typeId: 'exp', + typeId: DEMARCHES_TYPES_IDS.ExtensionDePerimetre, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.ExtensionDePerimetre, demarcheId10, firstEtapeDateValidator.parse('1879-07-26')).machineId ?? null, statutId: 'acc', etapes: [ { @@ -829,7 +895,7 @@ describe("phases d'une démarche", () => { ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1879-11-14'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -841,7 +907,7 @@ describe("phases d'une démarche", () => { ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1879-07-26'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -853,7 +919,8 @@ describe("phases d'une démarche", () => { titreId, id: demarcheId11, ordre: 1, - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId11, firstEtapeDateValidator.parse('1858-03-24')).machineId ?? null, statutId: 'acc', etapes: [ { @@ -862,7 +929,7 @@ describe("phases d'une démarche", () => { ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1858-03-24'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -874,7 +941,7 @@ describe("phases d'une démarche", () => { ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1858-03-24'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -884,7 +951,7 @@ describe("phases d'une démarche", () => { }, ] - const tested = titrePhasesFind(demarches, 'cxm') + const tested = titrePhasesFind(demarches, TITRES_TYPES_IDS.CONCESSION_METAUX) expect(tested).toStrictEqual({ [newDemarcheId('demarcheId11')]: { dateDebut: '1858-03-24', @@ -902,7 +969,8 @@ describe("phases d'une démarche", () => { titreId, id: demarcheIdProlongation, ordre: 11, - typeId: 'pro', + typeId: DEMARCHES_TYPES_IDS.Prolongation, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.Prolongation, demarcheIdProlongation, firstEtapeDateValidator.parse('2008-12-28')).machineId ?? null, statutId: 'cls', etapes: [ { @@ -911,7 +979,7 @@ describe("phases d'une démarche", () => { ordre: 3, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2011-04-07'), - typeId: 'css', + typeId: ETAPES_TYPES.classementSansSuite, statutId: 'fai', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -923,7 +991,7 @@ describe("phases d'une démarche", () => { ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2008-12-28'), - typeId: 'men', + typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: 'fai', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -936,7 +1004,7 @@ describe("phases d'une démarche", () => { isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2008-12-28'), duree: 60, - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, statutId: 'fai', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -948,7 +1016,8 @@ describe("phases d'une démarche", () => { titreId, id: demarcheIdOctroi, ordre: 1, - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdOctroi, firstEtapeDateValidator.parse('2000-03-24')).machineId ?? null, statutId: 'acc', etapes: [ { @@ -957,7 +1026,7 @@ describe("phases d'une démarche", () => { ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2000-03-24'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', duree: 120, concurrence: 'non-applicable', @@ -970,7 +1039,7 @@ describe("phases d'une démarche", () => { ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2000-03-24'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -980,7 +1049,7 @@ describe("phases d'une démarche", () => { }, ] - const tested = titrePhasesFind(demarches, 'cxm') + const tested = titrePhasesFind(demarches, TITRES_TYPES_IDS.CONCESSION_METAUX) expect(tested).toStrictEqual({ [demarcheIdOctroi]: { dateDebut: '2000-03-24', @@ -1001,7 +1070,8 @@ describe("phases d'une démarche", () => { titreId, id: demarcheIdOctroi, ordre: 1, - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdOctroi, firstEtapeDateValidator.parse('2000-03-24')).machineId ?? null, statutId: 'acc', etapes: [ { @@ -1010,7 +1080,7 @@ describe("phases d'une démarche", () => { ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2000-03-24'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', duree: 120, concurrence: 'non-applicable', @@ -1023,7 +1093,7 @@ describe("phases d'une démarche", () => { ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2000-03-24'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'rej', concurrence: 'non-applicable', hasTitreFrom: 'non-applicable', @@ -1033,7 +1103,7 @@ describe("phases d'une démarche", () => { }, ] - const tested = titrePhasesFind(demarches, 'cxm') + const tested = titrePhasesFind(demarches, TITRES_TYPES_IDS.CONCESSION_METAUX) expect(tested).toStrictEqual({}) }) @@ -1042,14 +1112,15 @@ describe("phases d'une démarche", () => { { id: newDemarcheId('demarcheId1'), titreId: newTitreId('titreId'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('demarcheId1'), firstEtapeDateValidator.parse('1970-09-09')).machineId ?? null, statutId: 'acc', ordre: 1, etapes: [ { id: newEtapeId('demarcheId1etapeId2'), titreDemarcheId: newDemarcheId('demarcheId1'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1061,7 +1132,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId1etapeId1'), titreDemarcheId: newDemarcheId('demarcheId1'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1075,7 +1146,8 @@ describe("phases d'une démarche", () => { { id: newDemarcheId('demarcheId2'), titreId: newTitreId('titreId'), - typeId: 'mut', + typeId: DEMARCHES_TYPES_IDS.Mutation, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.Mutation, newDemarcheId('demarcheId2'), firstEtapeDateValidator.parse('1994-10-13')).machineId ?? null, statutId: 'acc', ordre: 2, slug: demarcheSlugValidator.parse('m-cx-pontaubert-1970-mut01'), @@ -1083,7 +1155,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId2EtapeId2'), titreDemarcheId: newDemarcheId('demarcheId2'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1097,7 +1169,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId2EtapeId1'), titreDemarcheId: newDemarcheId('demarcheId2'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1112,14 +1184,16 @@ describe("phases d'une démarche", () => { { id: newDemarcheId('demarcheId3'), titreId: newTitreId('titreId'), - typeId: 'rec', + typeId: DEMARCHES_TYPES_IDS.RenonciationTotale, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.RenonciationTotale, newDemarcheId('demarcheId3'), firstEtapeDateValidator.parse('2019-11-20')).machineId ?? null, statutId: 'acc', ordre: 3, etapes: [ { id: newEtapeId('demarcheId3etapeId1'), titreDemarcheId: newDemarcheId('demarcheId3'), - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, statutId: 'fai', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1131,7 +1205,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId3etapeId2'), titreDemarcheId: newDemarcheId('demarcheId3'), - typeId: 'men', + typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: 'fai', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1143,7 +1217,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId3etapeId5'), titreDemarcheId: newDemarcheId('demarcheId3'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 5, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1155,7 +1229,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId3etapeId6'), titreDemarcheId: newDemarcheId('demarcheId3'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 6, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1167,7 +1241,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId3etapeId3'), titreDemarcheId: newDemarcheId('demarcheId3'), - typeId: 'apd', + typeId: ETAPES_TYPES.rapportEtAvisDeLaDREAL, statutId: 'fav', ordre: 3, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1179,7 +1253,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId3etapeId4'), titreDemarcheId: newDemarcheId('demarcheId3'), - typeId: 'app', + typeId: ETAPES_TYPES.avisDuPrefet, statutId: 'fav', ordre: 4, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1192,9 +1266,8 @@ describe("phases d'une démarche", () => { ], }, ] - const titreTypeId = 'cxm' - const tested = titrePhasesFind(demarches, titreTypeId) + const tested = titrePhasesFind(demarches, TITRES_TYPES_IDS.CONCESSION_METAUX) expect(tested).toStrictEqual({ [newDemarcheId('demarcheId1')]: { dateDebut: '1970-09-17', @@ -1212,14 +1285,15 @@ describe("phases d'une démarche", () => { { id: newDemarcheId('demarcheId1'), titreId: newTitreId('titreId'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('demarcheId1'), firstEtapeDateValidator.parse('1970-09-09')).machineId ?? null, statutId: 'acc', ordre: 1, etapes: [ { id: newEtapeId('demarcheId1etapeId2'), titreDemarcheId: newDemarcheId('demarcheId1'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1231,7 +1305,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId1etapeId1'), titreDemarcheId: newDemarcheId('demarcheId1'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1245,14 +1319,15 @@ describe("phases d'une démarche", () => { { id: newDemarcheId('demarcheId2'), titreId: newTitreId('titreId'), - typeId: 'mut', + typeId: DEMARCHES_TYPES_IDS.Mutation, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.Mutation, newDemarcheId('demarcheId2'), firstEtapeDateValidator.parse('1994-10-13')).machineId ?? null, statutId: 'acc', ordre: 2, etapes: [ { id: newEtapeId('demarcheId2EtapeId2'), titreDemarcheId: newDemarcheId('demarcheId2'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1266,7 +1341,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId2EtapeId1'), titreDemarcheId: newDemarcheId('demarcheId2'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1281,14 +1356,16 @@ describe("phases d'une démarche", () => { { id: newDemarcheId('demarcheId3'), titreId: newTitreId('titreId'), - typeId: 'rec', + typeId: DEMARCHES_TYPES_IDS.RenonciationTotale, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.RenonciationTotale, newDemarcheId('demarcheId3'), firstEtapeDateValidator.parse('2019-11-20')).machineId ?? null, statutId: 'acc', ordre: 3, etapes: [ { id: newEtapeId('demarcheId3etapeId1'), titreDemarcheId: newDemarcheId('demarcheId3'), - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, statutId: 'fai', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1300,7 +1377,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId3etapeId2'), titreDemarcheId: newDemarcheId('demarcheId3'), - typeId: 'men', + typeId: ETAPES_TYPES.enregistrementDeLaDemande, statutId: 'fai', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1312,7 +1389,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId3etapeId3'), titreDemarcheId: newDemarcheId('demarcheId3'), - typeId: 'apd', + typeId: ETAPES_TYPES.rapportEtAvisDeLaDREAL, statutId: 'fav', ordre: 3, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1324,7 +1401,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId3etapeId5'), titreDemarcheId: newDemarcheId('demarcheId3'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'aci', ordre: 5, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1336,7 +1413,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId3etapeId4'), titreDemarcheId: newDemarcheId('demarcheId3'), - typeId: 'app', + typeId: ETAPES_TYPES.avisDuPrefet, statutId: 'fav', ordre: 4, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1348,10 +1425,9 @@ describe("phases d'une démarche", () => { ], }, ] - const titreTypeId = 'cxm' // d'un côté on a une dim, de l'autre on a une dex suivie d'une dpu - const tested = titrePhasesFind(demarches, titreTypeId) + const tested = titrePhasesFind(demarches, TITRES_TYPES_IDS.CONCESSION_METAUX) expect(tested).toStrictEqual({ [newDemarcheId('demarcheId1')]: { dateDebut: '1970-09-17', @@ -1369,14 +1445,15 @@ describe("phases d'une démarche", () => { { id: newDemarcheId('demarcheId1'), titreId: newTitreId('titreId'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('demarcheId1'), firstEtapeDateValidator.parse('1968-01-13')).machineId ?? null, statutId: 'acc', ordre: 1, etapes: [ { id: newEtapeId('demarcheId1etapeId2'), titreDemarcheId: newDemarcheId('demarcheId1'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1388,7 +1465,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId1etapeId1'), titreDemarcheId: newDemarcheId('demarcheId1'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1403,13 +1480,16 @@ describe("phases d'une démarche", () => { id: newDemarcheId('demarcheId2'), titreId: newTitreId('titreId'), typeId: DEMARCHES_TYPES_IDS.ExtensionDePerimetre, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_METAUX, DEMARCHES_TYPES_IDS.ExtensionDePerimetre, newDemarcheId('demarcheId2'), firstEtapeDateValidator.parse('1981-09-09')).machineId ?? + null, statutId: 'acc', ordre: 2, etapes: [ { id: newEtapeId('demarcheId2EtapeId2'), titreDemarcheId: newDemarcheId('demarcheId2'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1422,7 +1502,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId2EtapeId1'), titreDemarcheId: newDemarcheId('demarcheId2'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1434,9 +1514,8 @@ describe("phases d'une démarche", () => { ], }, ] - const titreTypeId = 'cxm' - const tested = titrePhasesFind(demarches, titreTypeId) + const tested = titrePhasesFind(demarches, TITRES_TYPES_IDS.CONCESSION_METAUX) expect(tested).toStrictEqual({ [newDemarcheId('demarcheId1')]: { dateDebut: '1968-01-24', @@ -1453,14 +1532,17 @@ describe("phases d'une démarche", () => { { id: newDemarcheId('demarcheId1'), titreId: newTitreId('titreId'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('demarcheId1'), firstEtapeDateValidator.parse('2017-11-06')) + .machineId ?? null, statutId: 'acc', ordre: 1, etapes: [ { id: newEtapeId('demarcheId1etapeId2'), titreDemarcheId: newDemarcheId('demarcheId1'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1473,7 +1555,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId1etapeId1'), titreDemarcheId: newDemarcheId('demarcheId1'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1488,13 +1570,20 @@ describe("phases d'une démarche", () => { id: newDemarcheId('demarcheId2'), titreId: newTitreId('titreId'), typeId: DEMARCHES_TYPES_IDS.Prolongation1, + machineId: + MachineInfo.withDate( + TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_GRANULATS_MARINS, + DEMARCHES_TYPES_IDS.Prolongation1, + newDemarcheId('demarcheId2'), + firstEtapeDateValidator.parse('2023-01-01') + ).machineId ?? null, statutId: DemarchesStatutsIds.Rejete, ordre: 2, etapes: [ { id: newEtapeId('demarcheId2EtapeIdDex'), titreDemarcheId: newDemarcheId('demarcheId2'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'rej', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1507,7 +1596,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId2EtapeIdDpu'), titreDemarcheId: newDemarcheId('demarcheId2'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'fai', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1520,9 +1609,8 @@ describe("phases d'une démarche", () => { ], }, ] - const titreTypeId = 'prw' - const tested = titrePhasesFind(demarches, titreTypeId) + const tested = titrePhasesFind(demarches, TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_GRANULATS_MARINS) expect(tested).toStrictEqual({ [newDemarcheId('demarcheId1')]: { dateDebut: '2017-11-11', @@ -1539,14 +1627,17 @@ describe("phases d'une démarche", () => { { id: newDemarcheId('demarcheId1'), titreId: newTitreId('titreId'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('demarcheId1'), firstEtapeDateValidator.parse('2017-11-06')) + .machineId ?? null, statutId: 'acc', ordre: 1, etapes: [ { id: newEtapeId('demarcheId1etapeId2'), titreDemarcheId: newDemarcheId('demarcheId1'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1559,7 +1650,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId1etapeId1'), titreDemarcheId: newDemarcheId('demarcheId1'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1574,13 +1665,20 @@ describe("phases d'une démarche", () => { id: newDemarcheId('demarcheId2'), titreId: newTitreId('titreId'), typeId: DEMARCHES_TYPES_IDS.Prolongation1, + machineId: + MachineInfo.withDate( + TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_GRANULATS_MARINS, + DEMARCHES_TYPES_IDS.Prolongation1, + newDemarcheId('demarcheId2'), + firstEtapeDateValidator.parse('2022-07-08') + ).machineId ?? null, statutId: DemarchesStatutsIds.EnConstruction, ordre: 2, etapes: [ { id: newEtapeId('demarcheId2EtapeId2'), titreDemarcheId: newDemarcheId('demarcheId2'), - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, statutId: 'fai', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1593,9 +1691,8 @@ describe("phases d'une démarche", () => { ], }, ] - const titreTypeId = 'prw' - const tested = titrePhasesFind(demarches, titreTypeId) + const tested = titrePhasesFind(demarches, TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_GRANULATS_MARINS) expect(tested).toStrictEqual({ [newDemarcheId('demarcheId1')]: { dateDebut: '2017-11-11', @@ -1613,14 +1710,17 @@ describe("phases d'une démarche", () => { { id: newDemarcheId('demarcheId1'), titreId: newTitreId('titreId'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('demarcheId1'), firstEtapeDateValidator.parse('2017-11-06')) + .machineId ?? null, statutId: 'acc', ordre: 1, etapes: [ { id: newEtapeId('demarcheId1etapeId2'), titreDemarcheId: newDemarcheId('demarcheId1'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1633,7 +1733,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId1etapeId1'), titreDemarcheId: newDemarcheId('demarcheId1'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1648,13 +1748,20 @@ describe("phases d'une démarche", () => { id: newDemarcheId('demarcheId2'), titreId: newTitreId('titreId'), typeId: DEMARCHES_TYPES_IDS.Prolongation1, + machineId: + MachineInfo.withDate( + TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_GRANULATS_MARINS, + DEMARCHES_TYPES_IDS.Prolongation1, + newDemarcheId('demarcheId2'), + firstEtapeDateValidator.parse('2022-07-08') + ).machineId ?? null, statutId: DemarchesStatutsIds.EnConstruction, ordre: 2, etapes: [ { id: newEtapeId('demarcheId2EtapeId2'), titreDemarcheId: newDemarcheId('demarcheId2'), - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, statutId: ETAPES_STATUTS.FAIT, ordre: 2, isBrouillon: ETAPE_IS_BROUILLON, @@ -1667,9 +1774,8 @@ describe("phases d'une démarche", () => { ], }, ] - const titreTypeId = 'prw' - const tested = titrePhasesFind(demarches, titreTypeId) + const tested = titrePhasesFind(demarches, TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_GRANULATS_MARINS) expect(tested).toStrictEqual({ [newDemarcheId('demarcheId1')]: { dateDebut: '2017-11-11', @@ -1683,14 +1789,17 @@ describe("phases d'une démarche", () => { { id: newDemarcheId('demarcheId1'), titreId: newTitreId('titreId'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('demarcheId1'), firstEtapeDateValidator.parse('2017-11-06')) + .machineId ?? null, statutId: 'acc', ordre: 1, etapes: [ { id: newEtapeId('demarcheId1etapeId3'), titreDemarcheId: newDemarcheId('demarcheId1'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'rej', ordre: 3, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1702,7 +1811,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId1etapeId2'), titreDemarcheId: newDemarcheId('demarcheId1'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1715,7 +1824,7 @@ describe("phases d'une démarche", () => { { id: newEtapeId('demarcheId1etapeId1'), titreDemarcheId: newDemarcheId('demarcheId1'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -1728,7 +1837,7 @@ describe("phases d'une démarche", () => { }, ] - const tested = titrePhasesFind(demarches, 'prw') + const tested = titrePhasesFind(demarches, TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_GRANULATS_MARINS) expect(tested).toStrictEqual({ [newDemarcheId('demarcheId1')]: { dateDebut: '2017-11-11', @@ -1750,14 +1859,16 @@ describe("phases d'une démarche", () => { titreId, statutId: 'acc', ordre: 1, - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId1, firstEtapeDateValidator.parse('2010-10-18')).machineId ?? null, id: demarcheId1, etapes: [ { titreDemarcheId: demarcheId1, demarcheIdsConsentement: [], ordre: 2, - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, duree: 36, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2010-11-05'), @@ -1768,7 +1879,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId1, demarcheIdsConsentement: [], ordre: 1, - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2010-10-18'), statutId: 'acc', @@ -1779,14 +1890,17 @@ describe("phases d'une démarche", () => { titreId, statutId: 'acc', ordre: 2, - typeId: 'pr1', + typeId: DEMARCHES_TYPES_IDS.Prolongation1, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Prolongation1, demarcheId2, firstEtapeDateValidator.parse('2013-10-30')).machineId ?? + null, id: demarcheId2, etapes: [ { titreDemarcheId: demarcheId2, demarcheIdsConsentement: [], ordre: 5, - typeId: 'apd', + typeId: ETAPES_TYPES.rapportEtAvisDeLaDREAL, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2015-05-13'), statutId: 'fav', @@ -1795,7 +1909,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId2, demarcheIdsConsentement: [], ordre: 9, - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2015-12-04'), statutId: 'acc', @@ -1804,7 +1918,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId2, demarcheIdsConsentement: [], ordre: 8, - typeId: 'scg', + typeId: ETAPES_TYPES.saisinesEtAvisCGE_AE, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2015-11-09'), statutId: 'fav', @@ -1813,7 +1927,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId2, demarcheIdsConsentement: [], ordre: 1, - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, duree: 60, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2013-10-30'), @@ -1823,7 +1937,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId2, demarcheIdsConsentement: [], ordre: 6, - typeId: 'app', + typeId: ETAPES_TYPES.avisDuPrefet, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2015-06-04'), statutId: 'fav', @@ -1832,7 +1946,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId2, demarcheIdsConsentement: [], ordre: 7, - typeId: 'scg', + typeId: ETAPES_TYPES.saisinesEtAvisCGE_AE, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2015-10-08'), statutId: 'fai', @@ -1841,7 +1955,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId2, demarcheIdsConsentement: [], ordre: 10, - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, dateFin: toCaminoDate('2018-11-05'), isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2015-12-17'), @@ -1851,7 +1965,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId2, demarcheIdsConsentement: [], ordre: 3, - typeId: 'spp', + typeId: ETAPES_TYPES.saisineDuPrefet, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2013-11-19'), statutId: 'fai', @@ -1860,7 +1974,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId2, demarcheIdsConsentement: [], ordre: 2, - typeId: 'men', + typeId: ETAPES_TYPES.enregistrementDeLaDemande, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2013-10-30'), statutId: 'fai', @@ -1869,7 +1983,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId2, demarcheIdsConsentement: [], ordre: 4, - typeId: 'apo', + typeId: ETAPES_TYPES.avisDeLaCommissionDepartementaleDesMines_CDM_, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2015-02-11'), statutId: 'fav', @@ -1880,14 +1994,17 @@ describe("phases d'une démarche", () => { titreId, statutId: 'dep', ordre: 3, - typeId: 'vct', + typeId: DEMARCHES_TYPES_IDS.DemandeDeTitreDExploitation, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.DemandeDeTitreDExploitation, demarcheId3, firstEtapeDateValidator.parse('2015-07-31')) + .machineId ?? null, id: demarcheId3, etapes: [ { titreDemarcheId: demarcheId3, demarcheIdsConsentement: [], ordre: 2, - typeId: 'men', + typeId: ETAPES_TYPES.enregistrementDeLaDemande, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2015-07-31'), statutId: 'fai', @@ -1896,7 +2013,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId3, demarcheIdsConsentement: [], ordre: 1, - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, duree: 540, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2015-07-31'), @@ -1908,14 +2025,17 @@ describe("phases d'une démarche", () => { titreId, statutId: 'ins', ordre: 4, - typeId: 'pr2', + typeId: DEMARCHES_TYPES_IDS.Prolongation2, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Prolongation2, demarcheId4, firstEtapeDateValidator.parse('2018-07-04')).machineId ?? + null, id: demarcheId4, etapes: [ { titreDemarcheId: demarcheId4, demarcheIdsConsentement: [], ordre: 1, - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, duree: 60, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2018-06-29'), @@ -1925,7 +2045,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId4, demarcheIdsConsentement: [], ordre: 12, - typeId: 'apd', + typeId: ETAPES_TYPES.rapportEtAvisDeLaDREAL, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2021-07-30'), statutId: 'fav', @@ -1934,7 +2054,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId4, demarcheIdsConsentement: [], ordre: 4, - typeId: 'mco', + typeId: ETAPES_TYPES.demandeDeComplements, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2019-06-13'), statutId: 'fai', @@ -1943,7 +2063,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId4, demarcheIdsConsentement: [], ordre: 10, - typeId: 'asc', + typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2020-02-04'), statutId: 'fai', @@ -1952,7 +2072,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId4, demarcheIdsConsentement: [], ordre: 14, - typeId: 'apd', + typeId: ETAPES_TYPES.rapportEtAvisDeLaDREAL, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2021-12-16'), statutId: 'fav', @@ -1961,7 +2081,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId4, demarcheIdsConsentement: [], ordre: 5, - typeId: 'rco', + typeId: ETAPES_TYPES.receptionDeComplements, duree: 60, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2019-08-30'), @@ -1971,7 +2091,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId4, demarcheIdsConsentement: [], ordre: 2, - typeId: 'men', + typeId: ETAPES_TYPES.enregistrementDeLaDemande, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2018-07-04'), statutId: 'fai', @@ -1980,7 +2100,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId4, demarcheIdsConsentement: [], ordre: 15, - typeId: 'ppu', + typeId: ETAPES_TYPES.consultationDuPublic, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2023-01-18'), statutId: 'fai', @@ -1989,7 +2109,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId4, demarcheIdsConsentement: [], ordre: 6, - typeId: 'mco', + typeId: ETAPES_TYPES.demandeDeComplements, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2019-11-19'), statutId: 'fai', @@ -1998,7 +2118,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId4, demarcheIdsConsentement: [], ordre: 3, - typeId: 'spp', + typeId: ETAPES_TYPES.saisineDuPrefet, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2018-07-20'), statutId: 'fai', @@ -2007,7 +2127,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId4, demarcheIdsConsentement: [], ordre: 8, - typeId: 'mcr', + typeId: ETAPES_TYPES.recevabiliteDeLaDemande, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2020-01-29'), statutId: 'fav', @@ -2016,7 +2136,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId4, demarcheIdsConsentement: [], ordre: 7, - typeId: 'rco', + typeId: ETAPES_TYPES.receptionDeComplements, duree: 60, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2019-12-26'), @@ -2026,7 +2146,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: demarcheId4, demarcheIdsConsentement: [], ordre: 13, - typeId: 'apo', + typeId: ETAPES_TYPES.avisDeLaCommissionDepartementaleDesMines_CDM_, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2021-10-29'), statutId: 'fav', @@ -2034,7 +2154,7 @@ describe("phases d'une démarche", () => { ], }, ], - 'prm' + TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX ) ).toMatchInlineSnapshot(` { @@ -2062,14 +2182,17 @@ describe("phases d'une démarche", () => { titreId: newTitreId('nJ10z3Z74xi9OTh4oG6YXQBo'), statutId: 'acc', ordre: 1, - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('demarcheIdOctroi'), firstEtapeDateValidator.parse('2014-11-11')) + .machineId ?? null, id: newDemarcheId('demarcheIdOctroi'), etapes: [ { titreDemarcheId: newDemarcheId('demarcheIdOctroi'), demarcheIdsConsentement: [], ordre: 2, - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, dateFin: toCaminoDate('2014-11-11'), duree: 60, dateDebut: null, @@ -2082,7 +2205,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdOctroi'), demarcheIdsConsentement: [], ordre: 1, - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, dateFin: toCaminoDate('2014-11-11'), duree: 60, dateDebut: null, @@ -2097,14 +2220,17 @@ describe("phases d'une démarche", () => { titreId: newTitreId('EW9cDeM6PfXS4TPznkjsNZVO'), statutId: 'rej', ordre: 2, - typeId: 'pr1', + typeId: DEMARCHES_TYPES_IDS.Prolongation1, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Prolongation1, newDemarcheId('demarcheIdPr1'), firstEtapeDateValidator.parse('2014-09-24')) + .machineId ?? null, id: newDemarcheId('demarcheIdPr1'), etapes: [ { titreDemarcheId: newDemarcheId('demarcheIdPr1'), demarcheIdsConsentement: [], ordre: 3, - typeId: 'spp', + typeId: ETAPES_TYPES.saisineDuPrefet, dateFin: null, duree: null, dateDebut: null, @@ -2117,7 +2243,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdPr1'), demarcheIdsConsentement: [], ordre: 1, - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, dateFin: null, duree: 60, dateDebut: null, @@ -2130,7 +2256,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdPr1'), demarcheIdsConsentement: [], ordre: 4, - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, dateFin: null, duree: null, dateDebut: null, @@ -2143,7 +2269,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdPr1'), demarcheIdsConsentement: [], ordre: 2, - typeId: 'men', + typeId: ETAPES_TYPES.enregistrementDeLaDemande, dateFin: null, duree: null, dateDebut: null, @@ -2155,7 +2281,7 @@ describe("phases d'une démarche", () => { ], }, ], - 'pxm' + TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX ) ).toEqual({ demarcheIdOctroi: { @@ -2177,14 +2303,17 @@ describe("phases d'une démarche", () => { titreId: newTitreId('o3RzmZvqZcKMNmaE3nwXdvkE'), statutId: 'acc', ordre: 1, - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('demarcheIdOctroi'), firstEtapeDateValidator.parse('2009-11-17')) + .machineId ?? null, id: newDemarcheId('demarcheIdOctroi'), etapes: [ { titreDemarcheId: newDemarcheId('demarcheIdOctroi'), demarcheIdsConsentement: [], ordre: 2, - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, dateFin: toCaminoDate('2009-11-17'), duree: 60, dateDebut: null, @@ -2197,7 +2326,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdOctroi'), demarcheIdsConsentement: [], ordre: 1, - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, dateFin: toCaminoDate('2009-11-17'), duree: 60, dateDebut: null, @@ -2212,14 +2341,17 @@ describe("phases d'une démarche", () => { titreId: newTitreId('Mef8FKNlX0WtohaO9wGOMQZs'), statutId: 'des', ordre: 2, - typeId: 'pr1', + typeId: DEMARCHES_TYPES_IDS.Prolongation1, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Prolongation1, newDemarcheId('demarcheIdPr1'), firstEtapeDateValidator.parse('2009-08-17')) + .machineId ?? null, id: newDemarcheId('demarcheIdPr1'), etapes: [ { titreDemarcheId: newDemarcheId('demarcheIdPr1'), demarcheIdsConsentement: [], ordre: 1, - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, dateFin: null, duree: 24, dateDebut: null, @@ -2232,7 +2364,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdPr1'), demarcheIdsConsentement: [], ordre: 6, - typeId: 'app', + typeId: ETAPES_TYPES.avisDuPrefet, dateFin: null, duree: null, dateDebut: null, @@ -2245,7 +2377,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdPr1'), demarcheIdsConsentement: [], ordre: 3, - typeId: 'spp', + typeId: ETAPES_TYPES.saisineDuPrefet, dateFin: null, duree: null, dateDebut: null, @@ -2258,7 +2390,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdPr1'), demarcheIdsConsentement: [], ordre: 2, - typeId: 'men', + typeId: ETAPES_TYPES.enregistrementDeLaDemande, dateFin: null, duree: null, dateDebut: null, @@ -2271,7 +2403,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdPr1'), demarcheIdsConsentement: [], ordre: 7, - typeId: 'des', + typeId: ETAPES_TYPES.desistementDuDemandeur, dateFin: null, duree: null, dateDebut: null, @@ -2284,7 +2416,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdPr1'), demarcheIdsConsentement: [], ordre: 5, - typeId: 'apo', + typeId: ETAPES_TYPES.avisDeLaCommissionDepartementaleDesMines_CDM_, dateFin: null, duree: null, dateDebut: null, @@ -2297,7 +2429,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdPr1'), demarcheIdsConsentement: [], ordre: 4, - typeId: 'apd', + typeId: ETAPES_TYPES.rapportEtAvisDeLaDREAL, dateFin: null, duree: null, dateDebut: null, @@ -2309,7 +2441,7 @@ describe("phases d'une démarche", () => { ], }, ], - 'pxm' + TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX ) ).toEqual({ demarcheIdOctroi: { @@ -2331,14 +2463,17 @@ describe("phases d'une démarche", () => { titreId: newTitreId('nJ10z3Z74xi9OTh4oG6YXQBo'), statutId: 'acc', ordre: 1, - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('demarcheIdOctroi'), firstEtapeDateValidator.parse('2014-11-11')) + .machineId ?? null, id: newDemarcheId('demarcheIdOctroi'), etapes: [ { titreDemarcheId: newDemarcheId('demarcheIdOctroi'), demarcheIdsConsentement: [], ordre: 2, - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, dateFin: toCaminoDate('2014-11-11'), duree: 60, dateDebut: null, @@ -2351,7 +2486,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdOctroi'), demarcheIdsConsentement: [], ordre: 1, - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, dateFin: toCaminoDate('2014-11-11'), duree: 60, dateDebut: null, @@ -2366,14 +2501,17 @@ describe("phases d'une démarche", () => { titreId: newTitreId('EW9cDeM6PfXS4TPznkjsNZVO'), statutId: 'rej', ordre: 2, - typeId: 'pr1', + typeId: DEMARCHES_TYPES_IDS.Prolongation1, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Prolongation1, newDemarcheId('demarcheIdPr1'), firstEtapeDateValidator.parse('2014-09-24')) + .machineId ?? null, id: newDemarcheId('demarcheIdPr1'), etapes: [ { titreDemarcheId: newDemarcheId('demarcheIdPr1'), demarcheIdsConsentement: [], ordre: 4, - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, dateFin: null, duree: null, dateDebut: null, @@ -2386,7 +2524,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdPr1'), demarcheIdsConsentement: [], ordre: 2, - typeId: 'men', + typeId: ETAPES_TYPES.enregistrementDeLaDemande, dateFin: null, duree: null, dateDebut: null, @@ -2398,7 +2536,7 @@ describe("phases d'une démarche", () => { ], }, ], - 'pxm' + TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX ) ).toEqual({ demarcheIdOctroi: { @@ -2420,14 +2558,17 @@ describe("phases d'une démarche", () => { titreId: newTitreId('titreId'), statutId: 'acc', ordre: 1, - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('demarcheIdOctroi'), firstEtapeDateValidator.parse('2003-04-26')).machineId ?? + null, id: newDemarcheId('demarcheIdOctroi'), etapes: [ { titreDemarcheId: newDemarcheId('demarcheIdOctroi'), demarcheIdsConsentement: [], ordre: 3, - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, dateFin: toCaminoDate('2033-11-22'), dateDebut: toCaminoDate('2003-11-22'), isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -2439,7 +2580,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdOctroi'), demarcheIdsConsentement: [], ordre: 2, - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, dateFin: toCaminoDate('2033-11-22'), dateDebut: toCaminoDate('2003-11-22'), isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -2451,7 +2592,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdOctroi'), demarcheIdsConsentement: [], ordre: 1, - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2003-04-26'), statutId: 'rej', @@ -2460,7 +2601,7 @@ describe("phases d'une démarche", () => { ], }, ], - 'cxh' + TITRES_TYPES_IDS.CONCESSION_HYDROCARBURE ) ).toMatchInlineSnapshot(` { @@ -2480,14 +2621,17 @@ describe("phases d'une démarche", () => { titreId: newTitreId('titreId'), statutId: 'acc', ordre: 1, - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId('demarcheIdOctroi'), firstEtapeDateValidator.parse('2003-04-26')) + .machineId ?? null, id: newDemarcheId('demarcheIdOctroi'), etapes: [ { titreDemarcheId: newDemarcheId('demarcheIdOctroi'), demarcheIdsConsentement: [], ordre: 3, - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, dateFin: toCaminoDate('2033-11-23'), dateDebut: toCaminoDate('2003-11-23'), isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -2499,7 +2643,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdOctroi'), demarcheIdsConsentement: [], ordre: 2, - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, dateFin: toCaminoDate('2033-11-22'), dateDebut: toCaminoDate('2003-11-22'), isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -2511,7 +2655,7 @@ describe("phases d'une démarche", () => { titreDemarcheId: newDemarcheId('demarcheIdOctroi'), demarcheIdsConsentement: [], ordre: 1, - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2003-04-26'), statutId: 'acc', @@ -2520,7 +2664,7 @@ describe("phases d'une démarche", () => { ], }, ], - 'prm' + TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX ) ).toMatchInlineSnapshot(` { diff --git a/packages/api/src/business/rules/titre-phases-find.ts b/packages/api/src/business/rules/titre-phases-find.ts index 035488894..6a59c241c 100644 --- a/packages/api/src/business/rules/titre-phases-find.ts +++ b/packages/api/src/business/rules/titre-phases-find.ts @@ -1,5 +1,5 @@ import { ITitreDemarche, ITitreEtape } from '../../types' -import { demarcheEnregistrementDemandeDateFind, DemarcheId } from 'camino-common/src/demarche' +import { DemarcheId } from 'camino-common/src/demarche' import { titreEtapesSortAscByOrdre, titreEtapesSortDescByOrdre } from '../utils/titre-etapes-sort' import { titreEtapePublicationCheck } from './titre-etape-publication-check' @@ -13,9 +13,10 @@ import { demarcheStatutIdsSuccess, isDemarcheStatutNonStatue } from 'camino-comm import { ETAPES_TYPES, EtapeTypeId } from 'camino-common/src/static/etapesTypes' import { isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, isNullOrUndefinedOrEmpty, NonEmptyArray } from 'camino-common/src/typescript-tools' import { ETAPE_IS_NOT_BROUILLON } from 'camino-common/src/etape' -import { machineFind } from '../rules-demarches/machines' import { toMachineEtapes } from '../rules-demarches/machine-common' import { DemarcheStatus, getPhase } from '../rules-demarches/machine-helper' +import { MachineInfo } from 'camino-common/src/machines' +import { ApiMachineInfo } from '../rules-demarches/machines' const DATE_PAR_DEFAUT_TITRE_INFINI = toCaminoDate('2018-12-31') /** * trouve une démarche acceptée ou terminée qui est @@ -88,7 +89,15 @@ export const titrePhasesFind = (titreDemarches: TitreDemarchePhaseFind[], titreT }) const titreDemarcheAnnulation = titreDemarcheAnnulationFind(titreDemarches) - const titreDemarcheAnnulationDate = isTitreDemarchePhaseFindWithEtapes(titreDemarcheAnnulation) ? titreDemarcheAnnulationDateFinFind(titreTypeId, titreDemarcheAnnulation) : null + let titreDemarcheAnnulationDate: CaminoDate | null | undefined = null + if (isNotNullNorUndefined(titreDemarcheAnnulation)) { + const annulationMachineInfo = MachineInfo.withMachineId(titreTypeId, titreDemarcheAnnulation.typeId, titreDemarcheAnnulation.id, titreDemarcheAnnulation.machineId) + if (!annulationMachineInfo.valid) { + throw new Error(`La machine associée à la démarche est incohérente: ${annulationMachineInfo.error}`) + } + + titreDemarcheAnnulationDate = isTitreDemarchePhaseFindWithEtapes(titreDemarcheAnnulation) ? titreDemarcheAnnulationDateFinFind(annulationMachineInfo.value, titreDemarcheAnnulation.etapes) : null + } const filteredDemarches = sortedDemarches.filter( demarche => @@ -100,19 +109,24 @@ export const titrePhasesFind = (titreDemarches: TitreDemarchePhaseFind[], titreT if (!isTitreDemarchePhaseFindWithEtapes(demarche)) { return acc } - const machine = machineFind(titreTypeId, demarche.typeId, demarche.id, demarcheEnregistrementDemandeDateFind(demarche.fullEtapes)) + const machineInfo = MachineInfo.withMachineId(titreTypeId, demarche.typeId, demarche.id, demarche.machineId) + if (!machineInfo.valid) { + throw new Error(`La machine associée à la démarche est incohérente: ${machineInfo.error}`) + } + + const machine = new ApiMachineInfo(machineInfo.value) let phase - let statut: DemarcheStatus | undefined - if (isNotNullNorUndefined(machine)) { - statut = machine.demarcheStatut(toMachineEtapes(demarche.fullEtapes)) - phase = getPhase(statut) + let machineDemarcheStatut: DemarcheStatus | undefined + if (isNotNullNorUndefined(machine.machine)) { + machineDemarcheStatut = machine.machine.demarcheStatut(toMachineEtapes(demarche.fullEtapes)) + phase = getPhase(machineDemarcheStatut) } const isFirstPhase = acc.length === 0 let dateDebutTDE: CaminoDate | null | undefined = findDateDebut(demarche, titreTypeId, isFirstPhase || (acc[acc.length - 1].dateDeFinParDefaut ?? false)) if (isFirstPhase) { - if (isNotNullNorUndefined(machine) && isNotNullNorUndefined(statut)) { - if (demarcheStatutIdsSuccess.has(statut.demarcheStatut) && isNotNullNorUndefined(phase) && isNotNullNorUndefined(phase.debut) && isNotNullNorUndefined(phase.fin)) { + if (isNotNullNorUndefined(machineDemarcheStatut)) { + if (demarcheStatutIdsSuccess.has(machineDemarcheStatut.demarcheStatut) && isNotNullNorUndefined(phase) && isNotNullNorUndefined(phase.debut) && isNotNullNorUndefined(phase.fin)) { acc.push({ dateDebut: phase.debut, dateFin: phase.fin, @@ -156,17 +170,17 @@ export const titrePhasesFind = (titreDemarches: TitreDemarchePhaseFind[], titreT return acc } else { - if (isNotNullNorUndefined(machine) && isNotNullNorUndefined(statut)) { + if (isNotNullNorUndefined(machineDemarcheStatut)) { if (isNotNullNorUndefined(phase) && isNotNullNorUndefined(phase.debut)) { let dateDebut: CaminoDate = phase.debut let dateFin: CaminoDate | null = phase.fin - if ('demarcheDateDebut' in statut) { - if (isNotNullNorUndefined(statut.demarcheDateDebut.dateDebut)) { - acc[acc.length - 1].dateFin = statut.demarcheDateDebut.dateDebut + if ('demarcheDateDebut' in machineDemarcheStatut) { + if (isNotNullNorUndefined(machineDemarcheStatut.demarcheDateDebut.dateDebut)) { + acc[acc.length - 1].dateFin = machineDemarcheStatut.demarcheDateDebut.dateDebut } else { dateDebut = acc[acc.length - 1].dateFin ?? phase.debut // le ?? est pour typescript uniquement, la date de fin de la phase précédente ne PEUT PAS être null - if (isNotNullNorUndefined(statut.demarcheDateFin.duree)) { - dateFin = dateAddMonths(dateDebut, statut.demarcheDateFin.duree) + if (isNotNullNorUndefined(machineDemarcheStatut.demarcheDateFin.duree)) { + dateFin = dateAddMonths(dateDebut, machineDemarcheStatut.demarcheDateFin.duree) } } } @@ -246,8 +260,10 @@ export type TitreEtapePhaseFind = Pick< | 'surface' | 'hasTitreFrom' > -export type TitreDemarchePhaseFind = Pick<ITitreDemarche, 'statutId' | 'ordre' | 'typeId' | 'id' | 'titreId' | 'demarcheDateDebut' | 'demarcheDateFin'> & { etapes?: TitreEtapePhaseFind[] } -export type TitreDemarchePhaseFindWithEtapes = Pick<ITitreDemarche, 'statutId' | 'ordre' | 'typeId' | 'id' | 'titreId' | 'demarcheDateDebut' | 'demarcheDateFin'> & { +export type TitreDemarchePhaseFind = Pick<ITitreDemarche, 'statutId' | 'ordre' | 'typeId' | 'id' | 'titreId' | 'demarcheDateDebut' | 'demarcheDateFin' | 'machineId'> & { + etapes?: TitreEtapePhaseFind[] +} +type TitreDemarchePhaseFindWithEtapes = Pick<ITitreDemarche, 'statutId' | 'ordre' | 'typeId' | 'id' | 'titreId' | 'demarcheDateDebut' | 'demarcheDateFin' | 'machineId'> & { etapes: NonEmptyArray<TitreEtapePhaseFind> fullEtapes: NonEmptyArray<TitreEtapePhaseFind> } diff --git a/packages/api/src/business/rules/titre-prop-etape-find.test.ts b/packages/api/src/business/rules/titre-prop-etape-find.test.ts index 76f611c97..42431a8bd 100644 --- a/packages/api/src/business/rules/titre-prop-etape-find.test.ts +++ b/packages/api/src/business/rules/titre-prop-etape-find.test.ts @@ -2,7 +2,7 @@ import { ITitreDemarche, IPropId, ITitreEtape, ICommune } from '../../types' import { titreContenuTitreEtapeFind, titrePropTitreEtapeFind } from './titre-prop-etape-find' import { newDemarcheId, newEtapeId, newTitreId } from '../../database/models/_format/id-create' -import { toCaminoDate } from 'camino-common/src/date' +import { firstEtapeDateValidator, toCaminoDate } from 'camino-common/src/date' import { describe, expect, test } from 'vitest' import { TitresStatutIds } from 'camino-common/src/static/titresStatuts' import { newEntrepriseId } from 'camino-common/src/entreprise' @@ -10,6 +10,9 @@ import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' import { ETAPES_STATUTS } from 'camino-common/src/static/etapesStatuts' import { ETAPE_IS_NOT_BROUILLON, ETAPE_IS_BROUILLON } from 'camino-common/src/etape' import { km2Validator } from 'camino-common/src/number' +import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes' +import { MachineInfo } from 'camino-common/src/machines' +import { TITRES_TYPES_IDS } from 'camino-common/src/static/titresTypes' const currentDate = toCaminoDate('2023-04-06') describe("id de l'étape d'une propriété valide (dé-normalise)", () => { @@ -40,13 +43,13 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { [ { id: newDemarcheId('h-cx-courdemanges-1989-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: 'acc', etapes: [ { id: newEtapeId('h-cx-courdemanges-1989-oct01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1989-oct01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -56,7 +59,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { { id: newEtapeId('h-cx-courdemanges-1989-oct01-dex01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1989-oct01'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1989-01-01'), @@ -66,14 +69,14 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { }, { id: newDemarcheId('h-cx-courdemanges-1989-mut01'), - typeId: 'mut', + typeId: DEMARCHES_TYPES_IDS.Mutation, statutId: 'acc', ordre: 2, etapes: [ { id: newEtapeId('h-cx-courdemanges-1989-mut01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1989-mut01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1989-02-03'), @@ -83,7 +86,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { { id: newEtapeId('h-cx-courdemanges-1989-mut01-dex01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1989-mut01'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1989-02-02'), statutId: 'acc', @@ -105,13 +108,13 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { [ { id: newDemarcheId('h-cx-courdemanges-1988-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: 'acc', etapes: [ { id: newEtapeId('h-cx-courdemanges-1988-oct01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -121,7 +124,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { { id: newEtapeId('h-cx-courdemanges-1988-oct01-dex01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1988-oct01'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1989-01-01'), statutId: 'acc', @@ -162,13 +165,13 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { [ { id: newDemarcheId('h-cx-courdemanges-1986-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: 'acc', etapes: [ { id: newEtapeId('h-cx-courdemanges-1986-oct01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1986-oct01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1986-01-02'), statutId: 'acc', @@ -177,7 +180,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { { id: newEtapeId('h-cx-courdemanges-1986-oct01-dex01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1986-oct01'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1986-01-01'), @@ -187,14 +190,14 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { }, { id: newDemarcheId('h-cx-courdemanges-1986-mut01'), - typeId: 'mut', + typeId: DEMARCHES_TYPES_IDS.Mutation, statutId: 'acc', ordre: 2, etapes: [ { id: newEtapeId('h-cx-courdemanges-1986-mut01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1986-mut01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -205,7 +208,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { { id: newEtapeId('h-cx-courdemanges-1986-mut01-dex01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1986-mut01'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -227,13 +230,13 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { [ { id: newDemarcheId('h-cx-courdemanges-1986-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: 'acc', etapes: [ { id: newEtapeId('h-cx-courdemanges-1986-oct01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1986-oct01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -242,7 +245,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { { id: newEtapeId('h-cx-courdemanges-1986-oct01-dex01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1986-oct01'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -252,14 +255,14 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { }, { id: newDemarcheId('h-cx-courdemanges-1986-mut01'), - typeId: 'mut', + typeId: DEMARCHES_TYPES_IDS.Mutation, statutId: 'acc', ordre: 2, etapes: [ { id: newEtapeId('h-cx-courdemanges-1986-mut01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1986-mut01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -268,7 +271,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { { id: newEtapeId('h-cx-courdemanges-1986-mut01-dex01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1986-mut01'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -290,14 +293,14 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { [ { id: newDemarcheId('h-cx-courdemanges-1985-mut01'), - typeId: 'mut', + typeId: DEMARCHES_TYPES_IDS.Mutation, statutId: 'ins', ordre: 2, etapes: [ { id: newEtapeId('h-cx-courdemanges-1985-mut01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1985-mut01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1985-01-01'), @@ -307,7 +310,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { { id: newEtapeId('h-cx-courdemanges-1985-mut01-dex01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1985-mut01'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1985-01-01'), statutId: 'acc', @@ -317,13 +320,13 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { }, { id: newDemarcheId('h-cx-courdemanges-1985-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: 'ins', etapes: [ { id: newEtapeId('h-cx-courdemanges-1985-oct01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1985-oct01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -333,7 +336,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { { id: newEtapeId('h-cx-courdemanges-1985-oct01-dex01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1985-oct01'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -355,13 +358,13 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { [ { id: newDemarcheId('h-cx-courdemanges-1984-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: 'acc', etapes: [ { id: newEtapeId('h-cx-courdemanges-1984-oct01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1984-oct01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'rej', ordre: 2, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -373,7 +376,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { titreDemarcheId: newDemarcheId('h-cx-courdemanges-1984-oct01'), isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1984-01-01'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, statutId: 'rej', ordre: 1, }, @@ -393,7 +396,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { [ { id: newDemarcheId('h-cx-courdemanges-1983-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: 'acc', etapes: [ { @@ -401,7 +404,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1983-01-01'), titreDemarcheId: newDemarcheId(newDemarcheId('h-cx-courdemanges-1983-oct01')), - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, statutId: 'acc', ordre: 1, geojson4326Perimetre: { properties: {}, geometry: { type: 'MultiPolygon', coordinates: [[[[1, 2]]]] }, type: 'Feature' }, @@ -422,13 +425,13 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { [ { id: newDemarcheId('h-cx-courdemanges-1981-pro01'), - typeId: 'pro', + typeId: DEMARCHES_TYPES_IDS.Prolongation, statutId: 'ins', etapes: [ { id: newEtapeId('h-cx-courdemanges-1981-pro01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-pro01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1981-01-01'), @@ -439,13 +442,13 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { }, { id: newDemarcheId('h-cx-courdemanges-1981-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: 'acc', etapes: [ { id: newEtapeId('h-cx-courdemanges-1981-oct01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-oct01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1981-01-01'), statutId: 'acc', @@ -467,7 +470,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { [ { id: newDemarcheId('h-cx-courdemanges-1981-pro01'), - typeId: 'pro', + typeId: DEMARCHES_TYPES_IDS.Prolongation, statutId: 'ins', etapes: [ { @@ -482,13 +485,13 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { }, { id: newDemarcheId('h-cx-courdemanges-1981-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: 'acc', etapes: [ { id: newEtapeId('h-cx-courdemanges-1981-oct01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-oct01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1981-01-01'), statutId: 'acc', @@ -513,13 +516,13 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { [ { id: newDemarcheId('h-cx-courdemanges-1981-mut01'), - typeId: 'mut', + typeId: DEMARCHES_TYPES_IDS.Mutation, statutId: 'ins', etapes: [ { id: newEtapeId('h-cx-courdemanges-1981-mut01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-mut01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1981-01-01'), @@ -530,13 +533,13 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { }, { id: newDemarcheId('h-cx-courdemanges-1981-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: 'acc', etapes: [ { id: newEtapeId('h-cx-courdemanges-1981-oct01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-oct01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1981-01-01'), statutId: 'acc', @@ -560,7 +563,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { [ { id: newDemarcheId('h-cx-courdemanges-1981-pro01'), - typeId: 'pro', + typeId: DEMARCHES_TYPES_IDS.Prolongation, statutId: 'ins', ordre: 2, etapes: [ @@ -569,7 +572,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1981-01-01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-pro01'), - typeId: 'asc', + typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, statutId: 'fai', ordre: 1, geojson4326Perimetre: { type: 'Feature', properties: {}, geometry: { type: 'MultiPolygon', coordinates: [[[[1, 2]]]] } }, @@ -581,14 +584,14 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { }, { id: newDemarcheId('h-cx-courdemanges-1981-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: 'acc', ordre: 1, etapes: [ { id: newEtapeId('h-cx-courdemanges-1981-oct01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-oct01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -629,7 +632,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { [ { id: newDemarcheId('h-cx-courdemanges-1981-pro01'), - typeId: 'pro', + typeId: DEMARCHES_TYPES_IDS.Prolongation, statutId: 'ins', ordre: 2, etapes: [ @@ -638,7 +641,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1981-01-01'), titreDemarcheId: newDemarcheId(newDemarcheId('h-cx-courdemanges-1981-pro01')), - typeId: 'asc', + typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, statutId: 'fai', ordre: 1, geojson4326Perimetre: { type: 'Feature', properties: {}, geometry: { type: 'MultiPolygon', coordinates: [[[[1, 2]]]] } }, @@ -651,14 +654,14 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { }, { id: newDemarcheId('h-cx-courdemanges-1981-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: 'acc', ordre: 1, etapes: [ { id: newEtapeId('h-cx-courdemanges-1981-oct01-dpu01'), titreDemarcheId: newDemarcheId(newDemarcheId('h-cx-courdemanges-1981-oct01')), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1981-01-01'), @@ -699,13 +702,13 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { [ { id: newDemarcheId('h-cx-courdemanges-1982-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: 'acc', etapes: [ { id: newEtapeId('h-cx-courdemanges-1982-oct01-mfr01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1982-oct01'), - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, statutId: 'fai', ordre: 1, isBrouillon: ETAPE_IS_BROUILLON, @@ -732,7 +735,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { [ { id: newDemarcheId('h-cx-courdemanges-1982-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: 'acc', demarcheDateDebut: toCaminoDate('1982-01-01'), demarcheDateFin: toCaminoDate('2018-12-31'), @@ -740,7 +743,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { { id: newEtapeId('h-cx-courdemanges-1982-oct01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1982-oct01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 1, isBrouillon: ETAPE_IS_NOT_BROUILLON, @@ -765,13 +768,13 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { [ { id: newDemarcheId('h-cx-courdemanges-1982-amo01'), - typeId: 'amo', + typeId: DEMARCHES_TYPES_IDS.Amodiation, statutId: 'acc', etapes: [ { id: newEtapeId('h-cx-courdemanges-1982-amo01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1982-amo01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 1, dateFin: toCaminoDate('4018-12-31'), @@ -783,7 +786,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { }, { id: newDemarcheId('h-cx-courdemanges-1982-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: 'acc', demarcheDateDebut: toCaminoDate('2021-01-01'), demarcheDateFin: toCaminoDate('2022-01-01'), @@ -803,13 +806,13 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { [ { id: newDemarcheId('h-cx-courdemanges-1981-amo01'), - typeId: 'amo', + typeId: DEMARCHES_TYPES_IDS.Amodiation, statutId: 'acc', etapes: [ { id: newEtapeId('h-cx-courdemanges-1981-amo01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-amo01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1981-01-01'), @@ -820,13 +823,13 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { }, { id: newDemarcheId('h-cx-courdemanges-1981-pro01'), - typeId: 'pro', + typeId: DEMARCHES_TYPES_IDS.Prolongation, statutId: 'acc', etapes: [ { id: newEtapeId('h-cx-courdemanges-1981-pro01-dpu01'), titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-pro01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1981-01-01'), statutId: 'acc', @@ -836,7 +839,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { }, { id: newDemarcheId('h-cx-courdemanges-1981-oct01'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, statutId: 'acc', etapes: [ { @@ -844,7 +847,7 @@ describe("id de l'étape d'une propriété valide (dé-normalise)", () => { titreDemarcheId: newDemarcheId('h-cx-courdemanges-1981-oct01'), isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('1981-01-01'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, statutId: 'acc', ordre: 1, }, @@ -873,20 +876,23 @@ describe("id de l'étape qui a un contenu", () => { 'val' ) + const demarcheId = newDemarcheId('demarche-id') const etape3 = titreContenuTitreEtapeFind( { sectionId: 'arm', elementId: 'mecanisee' }, [ { - id: newDemarcheId('demarche-id'), + id: demarcheId, titreId: newTitreId('titre-id'), - typeId: 'pro', + typeId: DEMARCHES_TYPES_IDS.Prolongation, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Prolongation, demarcheId, firstEtapeDateValidator.parse('2020-01-01')).machineId ?? null, demarcheDateDebut: toCaminoDate('2020-01-01'), demarcheDateFin: toCaminoDate('2020-01-02'), etapes: [ { id: newEtapeId('etape-id'), - titreDemarcheId: newDemarcheId('demarche-id'), - typeId: 'dpu', + titreDemarcheId: demarcheId, + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2020-01-01'), statutId: 'acc', @@ -907,18 +913,21 @@ describe("id de l'étape qui a un contenu", () => { }) test("retourne l'id de l'étape si elle existe", () => { + const demarcheId = newDemarcheId('demarche-id') + const demarcheId2 = newDemarcheId('demarche-id-2') const etape1 = titreContenuTitreEtapeFind( { sectionId: 'arm', elementId: 'mecanisee' }, [ { - id: newDemarcheId('demarche-id'), + id: demarcheId, titreId: newTitreId('titre-id'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2020-01-03')).machineId ?? null, etapes: [ { id: newEtapeId('etape-id'), - titreDemarcheId: newDemarcheId('demarche-id'), - typeId: 'dpu', + titreDemarcheId: demarcheId, + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2020-01-03'), statutId: 'acc', @@ -930,14 +939,16 @@ describe("id de l'étape qui a un contenu", () => { ], }, { - id: newDemarcheId('demarche-id-2'), + id: demarcheId2, titreId: newTitreId('titre-id'), - typeId: 'pro', + typeId: DEMARCHES_TYPES_IDS.Prolongation, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Prolongation, demarcheId2, firstEtapeDateValidator.parse('2020-01-01')).machineId ?? null, etapes: [ { id: newEtapeId('etape-id-2'), - titreDemarcheId: newDemarcheId('demarche-id'), - typeId: 'dex', + titreDemarcheId: demarcheId2, + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2020-01-01'), statutId: 'fai', @@ -956,15 +967,17 @@ describe("id de l'étape qui a un contenu", () => { { sectionId: 'arm', elementId: 'mecanisee' }, [ { - id: newDemarcheId('demarche-id'), + id: demarcheId, titreId: newTitreId('titre-id'), - typeId: 'pro', + typeId: DEMARCHES_TYPES_IDS.Prolongation, + machineId: + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Prolongation, demarcheId, firstEtapeDateValidator.parse('2020-01-01')).machineId ?? null, statutId: 'acc', etapes: [ { id: newEtapeId('etape-id'), - titreDemarcheId: newDemarcheId('demarche-id'), - typeId: 'dpu', + titreDemarcheId: demarcheId, + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2020-01-01'), statutId: 'acc', @@ -983,18 +996,20 @@ describe("id de l'étape qui a un contenu", () => { }) test("ne retourne pas l'id de la demande si le titre n’est pas en dmi", () => { + const demarcheId = newDemarcheId('demarche-id') const etape = titreContenuTitreEtapeFind( { sectionId: 'arm', elementId: 'mecanisee' }, [ { - id: newDemarcheId('demarche-id'), + id: demarcheId, titreId: newTitreId('titre-id'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2020-01-03')).machineId ?? null, etapes: [ { id: newEtapeId('etape-id'), - titreDemarcheId: newDemarcheId('demarche-id'), - typeId: 'mfr', + titreDemarcheId: demarcheId, + typeId: ETAPES_TYPES.demande, isBrouillon: ETAPE_IS_BROUILLON, date: toCaminoDate('2020-01-03'), statutId: 'fai', @@ -1012,18 +1027,20 @@ describe("id de l'étape qui a un contenu", () => { }) test("retourne l'id de la demande si le titre est en dmi", () => { + const demarcheId = newDemarcheId('demarche-id') const etape = titreContenuTitreEtapeFind( { sectionId: 'arm', elementId: 'mecanisee' }, [ { - id: newDemarcheId('demarche-id'), + id: demarcheId, titreId: newTitreId('titre-id'), - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2020-01-03')).machineId ?? null, etapes: [ { id: newEtapeId('etape-id'), titreDemarcheId: newDemarcheId('demarche-id'), - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, isBrouillon: ETAPE_IS_BROUILLON, date: toCaminoDate('2020-01-03'), statutId: 'fai', diff --git a/packages/api/src/business/titre-etape-update.ts b/packages/api/src/business/titre-etape-update.ts index a669b992c..4ae7ae0a3 100644 --- a/packages/api/src/business/titre-etape-update.ts +++ b/packages/api/src/business/titre-etape-update.ts @@ -24,6 +24,7 @@ import { callAndExit } from '../tools/fp-tools' import { etapeMiseEnConcurrenceUpdate } from './processes/titres-etapes-mise-en-concurrence' import { etapesFondamentaleIdUpdate } from './processes/titres-etapes-fondamentale-id-update' import { etapeConsentementUpdate } from './processes/titres-etapes-consentement' +import { demarcheMachineIdUpdate } from './processes/demarche-machine-id-update' export const titreEtapeUpdateTask = async (pool: Pool, titreEtapeId: EtapeId | null, titreDemarcheId: DemarcheId, user: UserNotNull): Promise<void> => { try { @@ -55,6 +56,7 @@ export const titreEtapeUpdateTask = async (pool: Pool, titreEtapeId: EtapeId | n await titresEtapesHeritageContenuUpdate(pool, user, titreDemarcheId) const titreId = titreDemarche.titreId + await callAndExit(demarcheMachineIdUpdate(pool, titreDemarcheId)) await titresDemarchesStatutIdUpdate(pool, titreId) await titresDemarchesOrdreUpdate([titreId]) await titresDemarchesDatesUpdate(pool, [titreId]) diff --git a/packages/api/src/business/utils/titre-demarches-etapes-rebuild.ts b/packages/api/src/business/utils/titre-demarches-etapes-rebuild.ts index cbfdeac34..f0d9b3679 100644 --- a/packages/api/src/business/utils/titre-demarches-etapes-rebuild.ts +++ b/packages/api/src/business/utils/titre-demarches-etapes-rebuild.ts @@ -5,21 +5,16 @@ import { titrePhasesFind } from '../rules/titre-phases-find' import { CaminoDate } from 'camino-common/src/date' import { titreEtapeForMachineValidator } from '../rules-demarches/machine-common' import { isNotNullNorUndefinedNorEmpty, isNullOrUndefinedOrEmpty } from 'camino-common/src/typescript-tools' +import { MachineInfo } from 'camino-common/src/machines' /** * Filtre les étapes antérieures à une date - * @param titreEtapes - étapes d'une démarche - * @param date - date */ const titreEtapesFilter = (titreEtapes: ITitreEtape[], date: string) => titreEtapes.filter(titreEtape => titreEtape.date <= date) /** * Reconstruit les démarches et étapes antérieures à une date * et recalcule le statut des démarches en fonction des étapes - * @param date - date - * @param titreDemarches - démarches du titre - * @param titreTypeId - id du type du titre - * @returns démarches du titre */ export const titreDemarchesEtapesRebuild = (date: CaminoDate, titreDemarches: ITitreDemarche[], titreTypeId: TitreTypeId): (Omit<ITitreDemarche, 'etapes'> & { etapes: ITitreEtape[] })[] => { const titreDemarchesRebuilt: ReturnType<typeof titreDemarchesEtapesRebuild> = [] @@ -33,8 +28,14 @@ export const titreDemarchesEtapesRebuild = (date: CaminoDate, titreDemarches: IT if (isNotNullNorUndefinedNorEmpty(titreEtapesFiltered)) { const titreDemarche = { ...td, etapes: titreEtapesFiltered } + // TODO 2025-03-26 c'est hyper dangereux d'utiliser zod pour stripper les données à l'intérieur de notre code, ça doit être utilisé uniquement aux abords des API et de la BDD const etapes = titreDemarche.etapes.map(etape => titreEtapeForMachineValidator.parse(etape)) - titreDemarche.statutId = titreDemarcheStatutIdFind(titreDemarche.typeId, etapes, titreTypeId, titreDemarche.id) + const machineInfo = MachineInfo.withMachineId(titreTypeId, titreDemarche.typeId, titreDemarche.id, titreDemarche.machineId) + if (!machineInfo.valid) { + throw new Error(`La machine associée à la démarche est incohérente: ${machineInfo.error}`) + } + + titreDemarche.statutId = titreDemarcheStatutIdFind(machineInfo.value, etapes) titreDemarchesRebuilt.push(titreDemarche) } diff --git a/packages/api/src/business/utils/titre-etapes-sort.test.ts b/packages/api/src/business/utils/titre-etapes-sort.test.ts index 165918cd1..69b5ce6ee 100644 --- a/packages/api/src/business/utils/titre-etapes-sort.test.ts +++ b/packages/api/src/business/utils/titre-etapes-sort.test.ts @@ -1,21 +1,23 @@ import { titreEtapesSortAscByDate, titreEtapesSortAscByOrdre, titreEtapesSortDescByOrdre } from './titre-etapes-sort' import { newDemarcheId, newEtapeId } from '../../database/models/_format/id-create' import { vi, describe, test, expect } from 'vitest' -import { toCaminoDate } from 'camino-common/src/date' +import { firstEtapeDateValidator, toCaminoDate } from 'camino-common/src/date' import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes' import { TITRES_TYPES_IDS } from 'camino-common/src/static/titresTypes' import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' import { TitreEtapeForMachine } from '../rules-demarches/machine-common' import { ETAPE_IS_BROUILLON, ETAPE_IS_NOT_BROUILLON } from 'camino-common/src/etape' +import { MachineInfo } from 'camino-common/src/machines' +import { throwableMachineInfoForTestsOnly } from '../../../tests/_utils' const titreEtapesSortedDescResult = [ - { typeId: 'dpu', ordre: 2, date: '1988-03-11' }, - { typeId: 'dex', ordre: 1, date: '1988-03-06' }, + { typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, ordre: 2, date: '1988-03-11' }, + { typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, ordre: 1, date: '1988-03-06' }, ] as TitreEtapeForMachine[] const titreEtapesSortedAsc = [ - { typeId: 'dex', ordre: 1, date: '1988-03-06' }, - { typeId: 'dpu', ordre: 2, date: '1988-03-11' }, + { typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, ordre: 1, date: '1988-03-06' }, + { typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, ordre: 2, date: '1988-03-11' }, ] as TitreEtapeForMachine[] const titreEtapesSortedDesc = titreEtapesSortedAsc.slice().reverse() @@ -41,18 +43,22 @@ describe('trie les étapes', () => { }) test('des étapes organisées par date décroissante sont triées par date croissante', () => { - expect(titreEtapesSortAscByDate(titreEtapesSortedDesc, newDemarcheId(), 'oct', 'prh')).toMatchObject(titreEtapesSortedAsc) + expect( + titreEtapesSortAscByDate(titreEtapesSortedDesc, throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_HYDROCARBURE, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null)) + ).toMatchObject(titreEtapesSortedAsc) }) test('des étapes organisées par date croissante restent triées par date croissante', () => { - expect(titreEtapesSortAscByDate(titreEtapesSortedAsc, newDemarcheId(), 'oct', 'prh')).toMatchObject(titreEtapesSortedAsc) + expect( + titreEtapesSortAscByDate(titreEtapesSortedAsc, throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_HYDROCARBURE, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null)) + ).toMatchObject(titreEtapesSortedAsc) }) test('des étapes avec les mêmes dates organisées par ordre décroissant sont triées par ordre croissant', () => { const titreEtapesMemesDatesOrdreDesc: TitreEtapeForMachine[] = [ { id: newEtapeId('1'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, ordre: 2, date: toCaminoDate('1988-03-06'), dateFin: null, @@ -69,7 +75,7 @@ describe('trie les étapes', () => { }, { id: newEtapeId('2'), - typeId: 'dpu', + typeId: ETAPES_TYPES.publicationDeDecisionAuJORF, ordre: 1, date: toCaminoDate('1988-03-06'), dateFin: null, @@ -88,7 +94,12 @@ describe('trie les étapes', () => { const titreEtapesMemesDatesOrdreAscResult = titreEtapesMemesDatesOrdreDesc.slice().reverse() - expect(titreEtapesSortAscByDate(titreEtapesMemesDatesOrdreDesc, newDemarcheId(), 'oct', 'arm')).toStrictEqual(titreEtapesMemesDatesOrdreAscResult) + expect( + titreEtapesSortAscByDate( + titreEtapesMemesDatesOrdreDesc, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('1988-03-06')) + ) + ).toStrictEqual(titreEtapesMemesDatesOrdreAscResult) }) test('des étapes avec les mêmes dates sont triées par ordre de type croissant', () => { @@ -146,7 +157,12 @@ describe('trie les étapes', () => { demarcheIdsConsentement: [], }, ] - expect(titreEtapesSortAscByDate(titreEtapesMemesDatesOrdreEtapesTypesDesc, titreDemarcheId, DEMARCHES_TYPES_IDS.Retrait, TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX)).toMatchObject([ + expect( + titreEtapesSortAscByDate( + titreEtapesMemesDatesOrdreEtapesTypesDesc, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Retrait, titreDemarcheId, firstEtapeDateValidator.parse('1988-03-06')) + ) + ).toMatchObject([ { typeId: ETAPES_TYPES.saisineDuPrefet, ordre: 2, @@ -172,7 +188,7 @@ describe('trie les étapes', () => { const etapes: TitreEtapeForMachine[] = [ { id: newEtapeId('1'), - typeId: 'pfd', + typeId: ETAPES_TYPES.paiementDesFraisDeDossier, ordre: 1, date: toCaminoDate('2020-01-01'), dateFin: null, @@ -189,7 +205,7 @@ describe('trie les étapes', () => { }, { id: newEtapeId('2'), - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, ordre: 2, date: toCaminoDate('2020-01-01'), dateFin: null, @@ -206,7 +222,7 @@ describe('trie les étapes', () => { }, { id: newEtapeId('3'), - typeId: 'men', + typeId: ETAPES_TYPES.enregistrementDeLaDemande, ordre: 3, date: toCaminoDate('2020-01-01'), dateFin: null, @@ -223,7 +239,10 @@ describe('trie les étapes', () => { }, ] - const result = titreEtapesSortAscByDate(etapes, newDemarcheId(), DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX) + const result = titreEtapesSortAscByDate( + etapes, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')) + ) expect(result[0].typeId).toEqual('pfd') expect(result[1].typeId).toEqual('mfr') expect(result[2].typeId).toEqual('men') @@ -233,7 +252,7 @@ describe('trie les étapes', () => { const etapes: TitreEtapeForMachine[] = [ { id: newEtapeId('1'), - typeId: 'mcr', + typeId: ETAPES_TYPES.recevabiliteDeLaDemande, date: toCaminoDate('2020-01-01'), dateFin: null, dateDebut: null, @@ -267,7 +286,7 @@ describe('trie les étapes', () => { }, { id: newEtapeId('3'), - typeId: 'vfd', + typeId: ETAPES_TYPES.validationDuPaiementDesFraisDeDossier, date: toCaminoDate('2020-01-01'), dateFin: null, dateDebut: null, @@ -284,15 +303,18 @@ describe('trie les étapes', () => { }, ] - expect(() => titreEtapesSortAscByDate(etapes, newDemarcheId(), DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX)).toThrowErrorMatchingInlineSnapshot( - `[Error: l'état bof est inconnu]` - ) + expect(() => + titreEtapesSortAscByDate( + etapes, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')) + ) + ).toThrowErrorMatchingInlineSnapshot(`[Error: l'état bof est inconnu]`) }) test('utilise l’id pour trier des étapes totalement identiques', () => { const secondMcd: TitreEtapeForMachine = { id: newEtapeId('mcd2'), - typeId: 'mcd', + typeId: ETAPES_TYPES.demandeDeComplements_DecisionDeLaMissionAutoriteEnvironnementale_ExamenAuCasParCasDuProjet_, date: toCaminoDate('2020-01-01'), dateFin: null, dateDebut: null, @@ -312,7 +334,7 @@ describe('trie les étapes', () => { { id: newEtapeId('mfr'), ordre: 1, - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, date: toCaminoDate('2020-01-01'), dateFin: null, dateDebut: null, @@ -329,7 +351,7 @@ describe('trie les étapes', () => { { id: newEtapeId('men'), ordre: 2, - typeId: 'men', + typeId: ETAPES_TYPES.enregistrementDeLaDemande, date: toCaminoDate('2020-01-01'), dateFin: null, dateDebut: null, @@ -346,7 +368,7 @@ describe('trie les étapes', () => { { id: newEtapeId('mcd'), ordre: 3, - typeId: 'mcd', + typeId: ETAPES_TYPES.demandeDeComplements_DecisionDeLaMissionAutoriteEnvironnementale_ExamenAuCasParCasDuProjet_, date: toCaminoDate('2020-01-01'), dateFin: null, dateDebut: null, @@ -363,7 +385,7 @@ describe('trie les étapes', () => { { id: newEtapeId('rcd'), ordre: 4, - typeId: 'rcd', + typeId: ETAPES_TYPES.receptionDeComplements_DecisionDeLaMissionAutoriteEnvironnementale_ExamenAuCasParCasDuProjet__, date: toCaminoDate('2020-01-01'), dateFin: null, dateDebut: null, @@ -380,7 +402,10 @@ describe('trie les étapes', () => { secondMcd, ] - const result = titreEtapesSortAscByDate(etapes, newDemarcheId(), DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX) + const result = titreEtapesSortAscByDate( + etapes, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), firstEtapeDateValidator.parse('2020-01-01')) + ) expect(result).toContain(secondMcd) }) @@ -389,7 +414,7 @@ describe('trie les étapes', () => { { id: newEtapeId('mfr'), ordre: 1, - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, date: toCaminoDate('2020-01-01'), dateFin: null, dateDebut: null, @@ -406,7 +431,7 @@ describe('trie les étapes', () => { { id: newEtapeId('men'), ordre: 2, - typeId: 'men', + typeId: ETAPES_TYPES.enregistrementDeLaDemande, date: toCaminoDate('2020-01-02'), dateFin: null, dateDebut: null, @@ -423,7 +448,7 @@ describe('trie les étapes', () => { { id: newEtapeId('pfd'), ordre: 3, - typeId: 'pfd', + typeId: ETAPES_TYPES.paiementDesFraisDeDossier, date: toCaminoDate('2020-01-03'), dateFin: null, dateDebut: null, @@ -440,7 +465,7 @@ describe('trie les étapes', () => { { id: newEtapeId('mcp'), ordre: 4, - typeId: 'mcp', + typeId: ETAPES_TYPES.completudeDeLaDemande, date: toCaminoDate('2020-01-04'), dateFin: null, dateDebut: null, @@ -457,7 +482,7 @@ describe('trie les étapes', () => { { id: newEtapeId('vfd'), ordre: 5, - typeId: 'vfd', + typeId: ETAPES_TYPES.validationDuPaiementDesFraisDeDossier, date: toCaminoDate('2020-01-05'), dateFin: null, dateDebut: null, @@ -474,7 +499,7 @@ describe('trie les étapes', () => { { id: newEtapeId('asc'), ordre: 0, - typeId: 'asc', + typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, date: toCaminoDate('2020-01-07'), dateFin: null, dateDebut: null, @@ -491,7 +516,7 @@ describe('trie les étapes', () => { { id: newEtapeId('mcr'), ordre: 6, - typeId: 'pfd', + typeId: ETAPES_TYPES.paiementDesFraisDeDossier, date: toCaminoDate('2020-01-06'), dateFin: null, dateDebut: null, @@ -507,7 +532,7 @@ describe('trie les étapes', () => { }, ] - const result = titreEtapesSortAscByDate(etapes, newDemarcheId(), DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX) + const result = titreEtapesSortAscByDate(etapes, throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), null)) expect(result.map(({ id }) => id)).toMatchInlineSnapshot(` [ "mfr", @@ -526,7 +551,7 @@ describe('trie les étapes', () => { const etapes: TitreEtapeForMachine[] = [ { id: newEtapeId('mfr'), - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, date: toCaminoDate('2020-01-01'), dateFin: null, dateDebut: null, @@ -543,7 +568,7 @@ describe('trie les étapes', () => { }, { id: newEtapeId('dex'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, date: toCaminoDate('2020-01-01'), dateFin: null, dateDebut: null, @@ -559,7 +584,10 @@ describe('trie les étapes', () => { demarcheIdsConsentement: [], }, ] - const result = titreEtapesSortAscByDate(etapes, newDemarcheId(), DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_GEOTHERMIE) + const result = titreEtapesSortAscByDate( + etapes, + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_GEOTHERMIE, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), 'ProcedureSimplifiee') + ) expect(result.map(({ id }) => id)).toMatchInlineSnapshot(` [ @@ -573,7 +601,7 @@ describe('trie les étapes', () => { const etapes: TitreEtapeForMachine[] = [ { id: newEtapeId('mfr'), - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, date: toCaminoDate('2020-01-02'), dateFin: null, dateDebut: null, @@ -590,7 +618,7 @@ describe('trie les étapes', () => { }, { id: newEtapeId('dex'), - typeId: 'dex', + typeId: ETAPES_TYPES.decisionDeLAutoriteAdministrative, date: toCaminoDate('2020-01-01'), dateFin: null, dateDebut: null, @@ -606,7 +634,10 @@ describe('trie les étapes', () => { demarcheIdsConsentement: [], }, ] - const result = titreEtapesSortAscByDate(etapes, newDemarcheId(), DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_GEOTHERMIE) + const result = titreEtapesSortAscByDate( + etapes, + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_GEOTHERMIE, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), 'ProcedureSimplifiee') + ) expect(result.map(({ id }) => id)).toMatchInlineSnapshot(` [ diff --git a/packages/api/src/business/utils/titre-etapes-sort.ts b/packages/api/src/business/utils/titre-etapes-sort.ts index 6d1225a9d..72eea3f42 100644 --- a/packages/api/src/business/utils/titre-etapes-sort.ts +++ b/packages/api/src/business/utils/titre-etapes-sort.ts @@ -1,13 +1,11 @@ import { ITitreEtape } from '../../types' import { TitreEtapeForMachine, toMachineEtapes } from '../rules-demarches/machine-common' -import { TitreTypeId } from 'camino-common/src/static/titresTypes' -import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' import { getEtapesTDE } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/index' -import { demarcheEnregistrementDemandeDateFind, DemarcheId } from 'camino-common/src/demarche' -import { isNotNullNorUndefinedNorEmpty } from 'camino-common/src/typescript-tools' +import { isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty } from 'camino-common/src/typescript-tools' import { ETAPE_IS_BROUILLON } from 'camino-common/src/etape' import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' -import { CaminoMachines, machineFind } from '../rules-demarches/machines' +import { ApiMachineInfo } from '../rules-demarches/machines' +import { MachineInfo } from 'camino-common/src/machines' // classe les étapes selon leur ordre inverse: 3, 2, 1. export const titreEtapesSortDescByOrdre = <T extends Pick<ITitreEtape, 'ordre'>>(titreEtapes: T[]): T[] => titreEtapes.toSorted((a, b) => b.ordre! - a.ordre!) @@ -15,17 +13,13 @@ export const titreEtapesSortDescByOrdre = <T extends Pick<ITitreEtape, 'ordre'>> // classe les étapes selon leur ordre: 1, 2, 3, … export const titreEtapesSortAscByOrdre = <T extends Pick<ITitreEtape, 'ordre'>>(titreEtapes: T[]): T[] => titreEtapes.toSorted((a, b) => a.ordre! - b.ordre!) // classe les étapes selon leur dates, ordre et etapesTypes.ordre le cas échéant -export const titreEtapesSortAscByDate = <T extends TitreEtapeForMachine>(titreEtapes: T[], demarcheId: DemarcheId, demarcheTypeId: DemarcheTypeId, titreTypeId: TitreTypeId): T[] => { - const firstEtapeDate = demarcheEnregistrementDemandeDateFind(titreEtapes) - let machine: CaminoMachines | undefined - if (isNotNullNorUndefinedNorEmpty(firstEtapeDate)) { - machine = machineFind(titreTypeId, demarcheTypeId, demarcheId, firstEtapeDate) - } +export const titreEtapesSortAscByDate = <T extends TitreEtapeForMachine>(titreEtapes: T[], machineInfo: MachineInfo): T[] => { + const machine = new ApiMachineInfo(machineInfo) - if (machine) { - const etapes = machine.orderMachine(toMachineEtapes(titreEtapes)) - if (!machine.isEtapesOk(etapes)) { - console.error(`impossible de trouver un ordre pour la démarche '${demarcheId}' où ces étapes sont valides ${JSON.stringify(etapes)}`) + if (isNotNullNorUndefined(machine.machine)) { + const etapes = machine.machine.orderMachine(toMachineEtapes(titreEtapes)) + if (!machine.machine.isEtapesOk(etapes)) { + console.error(`impossible de trouver un ordre pour la démarche '${machine.demarcheId}' où ces étapes sont valides ${JSON.stringify(etapes)}`) } const result: T[] = [] @@ -69,13 +63,13 @@ export const titreEtapesSortAscByDate = <T extends TitreEtapeForMachine>(titreEt if (dateA < dateB) return -1 if (dateA > dateB) return 1 - const etapes = getEtapesTDE(titreTypeId, demarcheTypeId) + const etapes = getEtapesTDE(machine.titreTypeId, machine.demarcheTypeId) const aTypeIndex = etapes.findIndex(e => e === a.typeId) const bTypeIndex = etapes.findIndex(e => e === b.typeId) if (aTypeIndex === -1 || bTypeIndex === -1) { - console.warn(`${demarcheId}: les étapes ${a.typeId} ou ${b.typeId} ne devraient pas être possible pour une démarche de type ${demarcheTypeId}`) + console.warn(`${machine.demarcheId}: les étapes ${a.typeId} ou ${b.typeId} ne devraient pas être possible pour une démarche de type ${machine.demarcheTypeId}`) return a.ordre! - b.ordre! } diff --git a/packages/api/src/business/utils/titre-slug-and-relations-update.test.integration.ts b/packages/api/src/business/utils/titre-slug-and-relations-update.test.integration.ts index 838a53904..976158177 100644 --- a/packages/api/src/business/utils/titre-slug-and-relations-update.test.integration.ts +++ b/packages/api/src/business/utils/titre-slug-and-relations-update.test.integration.ts @@ -11,6 +11,7 @@ import { insertTitreGraph } from '../../../tests/integration-test-helper' import { isNullOrUndefined } from 'camino-common/src/typescript-tools' import { newDemarcheId, newTitreId } from '../../database/models/_format/id-create' import { demarcheSlugValidator } from 'camino-common/src/demarche' +import { throwableMachineInfoForTestsOnly } from '../../../tests/_utils' beforeAll(async () => { await dbManager.populateDb() }) @@ -132,6 +133,7 @@ describe('vérifie la mis à jour des slugs sur les relations d’un titre', () test('génère un slug pour une démarche', async () => { await Titres.query().delete() const id = newTitreId() + const demarcheId = newDemarcheId() const titre = await titreAdd({ nom: 'titre-nom', id, @@ -141,10 +143,11 @@ describe('vérifie la mis à jour des slugs sur les relations d’un titre', () slug: titreSlugValidator.parse('m-ar-titre-nom-0000'), demarches: [ { - id: newDemarcheId(), + id: demarcheId, titreId: id, typeId: 'oct', statutId: 'dep', + machineId: throwableMachineInfoForTestsOnly('arm', 'oct', demarcheId, null).machineId ?? null, slug: demarcheSlugValidator.parse('slug'), }, ], diff --git a/packages/api/src/business/validations/titre-demarche-etat-validate.test.ts b/packages/api/src/business/validations/titre-demarche-etat-validate.test.ts index 97e529467..6eb6a0d8e 100644 --- a/packages/api/src/business/validations/titre-demarche-etat-validate.test.ts +++ b/packages/api/src/business/validations/titre-demarche-etat-validate.test.ts @@ -4,30 +4,28 @@ import { getPossiblesEtapesTypes, titreDemarcheUpdatedEtatValidate } from './tit import { newDemarcheId, newEtapeId } from '../../database/models/_format/id-create' import { EtapesTypesEtapesStatuts } from 'camino-common/src/static/etapesTypesEtapesStatuts' import { describe, test, expect, vi } from 'vitest' -import { caminoDateValidator, dateAddDays, toCaminoDate } from 'camino-common/src/date' +import { caminoDateValidator, dateAddDays, firstEtapeDateValidator, toCaminoDate } from 'camino-common/src/date' import { ETAPES_TYPES, EtapeTypeId } from 'camino-common/src/static/etapesTypes' import { ETAPE_IS_BROUILLON, ETAPE_IS_NOT_BROUILLON, etapeIdValidator } from 'camino-common/src/etape' -import { ArmOctMachine } from '../rules-demarches/arm/oct.machine' import { TitreEtapeForMachine } from '../rules-demarches/machine-common' import { communeIdValidator, toCommuneId } from 'camino-common/src/static/communes' import { km2Validator } from 'camino-common/src/number' -import { ProcedureSpecifiqueMachine } from '../rules-demarches/procedure-specifique/procedure-specifique.machine' import { ETAPES_STATUTS } from 'camino-common/src/static/etapesStatuts' import { TITRES_TYPES_IDS } from 'camino-common/src/static/titresTypes' import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes' -import { PrmOctMachine } from '../rules-demarches/prm/oct.machine' +import { MachineInfo } from 'camino-common/src/machines' +import { ApiMachineInfo } from '../rules-demarches/machines' +import { throwableMachineInfoForTestsOnly } from '../../../tests/_utils' console.warn = vi.fn() describe('titreDemarcheUpdatedEtatValidate', () => { test('ajoute une étape à une démarche vide', () => { const demarcheId = newDemarcheId() + const machineInfo = throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, null) const valid = titreDemarcheUpdatedEtatValidate( - 'oct', - { - typeId: 'arm', - demarches: [{ id: demarcheId }], - }, + machineInfo, + [{ id: demarcheId }], { typeId: 'mfr', date: caminoDateValidator.parse('2030-01-01'), @@ -40,8 +38,7 @@ describe('titreDemarcheUpdatedEtatValidate', () => { hasTitreFrom: true, demarcheIdsConsentement: [], }, - demarcheId, - null + [] ) expect(valid.valid).toBe(true) @@ -49,12 +46,10 @@ describe('titreDemarcheUpdatedEtatValidate', () => { test('ajoute une étape à une démarche qui contient déjà une étape', () => { const demarcheId = newDemarcheId() + const machineInfo = MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2022-05-03')) const valid = titreDemarcheUpdatedEtatValidate( - 'oct', - { - typeId: 'arm', - demarches: [{ id: demarcheId }], - }, + machineInfo, + [{ id: demarcheId }], { typeId: 'men', statutId: 'fai', @@ -67,8 +62,6 @@ describe('titreDemarcheUpdatedEtatValidate', () => { hasTitreFrom: true, demarcheIdsConsentement: [], }, - demarcheId, - [ { id: newEtapeId('1'), @@ -109,95 +102,87 @@ describe('titreDemarcheUpdatedEtatValidate', () => { hasTitreFrom: true, demarcheIdsConsentement: [], } - const valid = titreDemarcheUpdatedEtatValidate( - 'oct', + const machineInfo = MachineInfo.withDate('prm', DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2020-12-17')) + const valid = titreDemarcheUpdatedEtatValidate(machineInfo, [{ id: demarcheId }], demande, [ + demande, { - typeId: 'prm', - demarches: [{ id: demarcheId }], + id: etapeIdValidator.parse('idMdp'), + typeId: 'men', + statutId: 'fai', + isBrouillon: ETAPE_IS_NOT_BROUILLON, + date: toCaminoDate('2020-12-17'), + ordre: 2, + concurrence: { amIFirst: true }, + hasTitreFrom: true, + demarcheIdsConsentement: [], }, - demande, - demarcheId, - [ - demande, - { - id: etapeIdValidator.parse('idMdp'), - typeId: 'men', - statutId: 'fai', - isBrouillon: ETAPE_IS_NOT_BROUILLON, - date: toCaminoDate('2020-12-17'), - ordre: 2, - concurrence: { amIFirst: true }, - hasTitreFrom: true, - demarcheIdsConsentement: [], - }, - { - id: etapeIdValidator.parse('idSpp'), - typeId: 'spp', - statutId: 'fai', - isBrouillon: ETAPE_IS_NOT_BROUILLON, - date: toCaminoDate('2021-01-18'), - ordre: 3, - concurrence: { amIFirst: true }, - hasTitreFrom: true, - demarcheIdsConsentement: [], - }, - { - id: etapeIdValidator.parse('idMcr'), - typeId: 'mcr', - statutId: 'fav', - isBrouillon: ETAPE_IS_NOT_BROUILLON, - date: toCaminoDate('2022-11-17'), - ordre: 4, - concurrence: { amIFirst: true }, - hasTitreFrom: true, - demarcheIdsConsentement: [], - }, - { - id: etapeIdValidator.parse('idAnf'), - typeId: 'anf', - statutId: 'ter', - isBrouillon: ETAPE_IS_NOT_BROUILLON, - date: toCaminoDate('2022-11-17'), - ordre: 5, - concurrence: { amIFirst: true }, - hasTitreFrom: true, - demarcheIdsConsentement: [], - }, - { - id: etapeIdValidator.parse('idAsc'), - typeId: 'asc', - statutId: 'fai', - isBrouillon: ETAPE_IS_NOT_BROUILLON, - date: toCaminoDate('2022-11-17'), - ordre: 6, - concurrence: { amIFirst: true }, - hasTitreFrom: true, - demarcheIdsConsentement: [], - }, - { - id: etapeIdValidator.parse('idAdc'), - typeId: 'adc', - statutId: 'fai', - isBrouillon: ETAPE_IS_NOT_BROUILLON, - date: toCaminoDate('2022-11-17'), - ordre: 7, - concurrence: { amIFirst: true }, - hasTitreFrom: true, - demarcheIdsConsentement: [], - }, - { - id: etapeIdValidator.parse('idApo'), - typeId: 'apo', - statutId: 'fav', - isBrouillon: ETAPE_IS_NOT_BROUILLON, - date: toCaminoDate('2023-02-08'), - ordre: 8, - concurrence: { amIFirst: true }, - hasTitreFrom: true, - demarcheIdsConsentement: [], - }, - ] - ) + { + id: etapeIdValidator.parse('idSpp'), + typeId: 'spp', + statutId: 'fai', + isBrouillon: ETAPE_IS_NOT_BROUILLON, + date: toCaminoDate('2021-01-18'), + ordre: 3, + concurrence: { amIFirst: true }, + hasTitreFrom: true, + demarcheIdsConsentement: [], + }, + { + id: etapeIdValidator.parse('idMcr'), + typeId: 'mcr', + statutId: 'fav', + isBrouillon: ETAPE_IS_NOT_BROUILLON, + date: toCaminoDate('2022-11-17'), + ordre: 4, + concurrence: { amIFirst: true }, + hasTitreFrom: true, + demarcheIdsConsentement: [], + }, + { + id: etapeIdValidator.parse('idAnf'), + typeId: 'anf', + statutId: 'ter', + isBrouillon: ETAPE_IS_NOT_BROUILLON, + date: toCaminoDate('2022-11-17'), + ordre: 5, + concurrence: { amIFirst: true }, + hasTitreFrom: true, + demarcheIdsConsentement: [], + }, + { + id: etapeIdValidator.parse('idAsc'), + typeId: 'asc', + statutId: 'fai', + isBrouillon: ETAPE_IS_NOT_BROUILLON, + date: toCaminoDate('2022-11-17'), + ordre: 6, + concurrence: { amIFirst: true }, + hasTitreFrom: true, + demarcheIdsConsentement: [], + }, + { + id: etapeIdValidator.parse('idAdc'), + typeId: 'adc', + statutId: 'fai', + isBrouillon: ETAPE_IS_NOT_BROUILLON, + date: toCaminoDate('2022-11-17'), + ordre: 7, + concurrence: { amIFirst: true }, + hasTitreFrom: true, + demarcheIdsConsentement: [], + }, + { + id: etapeIdValidator.parse('idApo'), + typeId: 'apo', + statutId: 'fav', + isBrouillon: ETAPE_IS_NOT_BROUILLON, + date: toCaminoDate('2023-02-08'), + ordre: 8, + concurrence: { amIFirst: true }, + hasTitreFrom: true, + demarcheIdsConsentement: [], + }, + ]) expect(valid).toMatchInlineSnapshot(` { @@ -209,12 +194,10 @@ describe('titreDemarcheUpdatedEtatValidate', () => { test('modifie une étape à une démarche', () => { const demarcheId = newDemarcheId() + const machineInfo = MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2022-05-04')) const valid = titreDemarcheUpdatedEtatValidate( - 'oct', - { - typeId: 'arm', - demarches: [{ id: demarcheId }], - }, + machineInfo, + [{ id: demarcheId }], { id: newEtapeId('1'), typeId: 'mfr', @@ -228,8 +211,6 @@ describe('titreDemarcheUpdatedEtatValidate', () => { hasTitreFrom: true, demarcheIdsConsentement: [], }, - demarcheId, - [ { id: newEtapeId('1'), @@ -267,12 +248,10 @@ describe('titreDemarcheUpdatedEtatValidate', () => { test('l’ajout d’une étape d’une démarche historique est valide', () => { const demarcheId = newDemarcheId() + const machineInfo = MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2000-01-01')) const valid = titreDemarcheUpdatedEtatValidate( - 'oct', - { - typeId: 'arm', - demarches: [{ id: demarcheId }], - }, + machineInfo, + [{ id: demarcheId }], { typeId: 'mfr', isBrouillon: ETAPE_IS_BROUILLON, @@ -282,8 +261,6 @@ describe('titreDemarcheUpdatedEtatValidate', () => { demarcheIdsConsentement: [], hasTitreFrom: true, }, - demarcheId, - [ { id: etapeIdValidator.parse('1'), @@ -309,22 +286,19 @@ describe('titreDemarcheUpdatedEtatValidate', () => { test('l’ajout d’une étape à une démarche sans étape est valide', () => { const demarcheId = newDemarcheId() + const machineInfo = throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, null) const valid = titreDemarcheUpdatedEtatValidate( - 'oct', - { - typeId: 'arm', - demarches: [{ id: demarcheId }], - }, + machineInfo, + [{ id: demarcheId }], { - typeId: 'mfr', + typeId: ETAPES_TYPES.demande, isBrouillon: ETAPE_IS_BROUILLON, date: caminoDateValidator.parse('2000-01-01'), - statutId: 'fai', + statutId: ETAPES_STATUTS.FAIT, concurrence: { amIFirst: true }, demarcheIdsConsentement: [], hasTitreFrom: true, }, - demarcheId, [] ) @@ -333,25 +307,21 @@ describe('titreDemarcheUpdatedEtatValidate', () => { test("retourne une erreur si la démarche en cours de modification n'existe pas", () => { const demarcheId = newDemarcheId() + const etapeDate = caminoDateValidator.parse('2000-01-01') expect( titreDemarcheUpdatedEtatValidate( - 'oct', - { - typeId: 'arm', - demarches: [{ id: newDemarcheId() }], - }, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse(etapeDate)), + [{ id: newDemarcheId() }], { id: etapeIdValidator.parse('1'), typeId: ETAPES_TYPES.demande, - date: caminoDateValidator.parse('2000-01-01'), + date: etapeDate, concurrence: { amIFirst: true }, hasTitreFrom: true, statutId: ETAPES_STATUTS.FAIT, isBrouillon: ETAPE_IS_NOT_BROUILLON, demarcheIdsConsentement: [], }, - demarcheId, - [] ) ).toMatchInlineSnapshot(` @@ -363,17 +333,15 @@ describe('titreDemarcheUpdatedEtatValidate', () => { } `) + const newEtapeDate = caminoDateValidator.parse('2025-01-01') expect( titreDemarcheUpdatedEtatValidate( - 'oct', - { - typeId: 'arm', - demarches: [{ id: demarcheId }], - }, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse(newEtapeDate)), + [{ id: demarcheId }], { id: etapeIdValidator.parse('1'), typeId: ETAPES_TYPES.demande, - date: caminoDateValidator.parse('2025-01-01'), + date: newEtapeDate, concurrence: { amIFirst: true }, hasTitreFrom: false, statutId: ETAPES_STATUTS.FAIT, @@ -382,8 +350,6 @@ describe('titreDemarcheUpdatedEtatValidate', () => { communes: [{ id: toCommuneId('97300') }], surface: km2Validator.parse(12), }, - demarcheId, - [] ) ).toMatchInlineSnapshot(` @@ -396,12 +362,10 @@ describe('titreDemarcheUpdatedEtatValidate', () => { test('supprime une étape', () => { const demarcheId = newDemarcheId() + const machineInfo = MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2003-01-01')) const valid = titreDemarcheUpdatedEtatValidate( - 'oct', - { - typeId: 'arm', - demarches: [{ id: demarcheId }], - }, + machineInfo, + [{ id: demarcheId }], { id: etapeIdValidator.parse('1'), typeId: 'mfr', @@ -412,7 +376,6 @@ describe('titreDemarcheUpdatedEtatValidate', () => { hasTitreFrom: true, demarcheIdsConsentement: [], }, - demarcheId, [ { id: etapeIdValidator.parse('1'), @@ -434,16 +397,10 @@ describe('titreDemarcheUpdatedEtatValidate', () => { test('ajoute une étape à une démarche sans machine', () => { const demarcheId = newDemarcheId() + const machineInfo = throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, null) const valid = titreDemarcheUpdatedEtatValidate( - 'oct', - { - typeId: 'arm', - demarches: [ - { - id: demarcheId, - }, - ], - }, + machineInfo, + [{ id: demarcheId }], { id: etapeIdValidator.parse('1'), typeId: ETAPES_TYPES.demande, @@ -454,7 +411,7 @@ describe('titreDemarcheUpdatedEtatValidate', () => { isBrouillon: ETAPE_IS_NOT_BROUILLON, demarcheIdsConsentement: [], }, - demarcheId + [] ) expect(valid.valid).toBe(true) @@ -462,12 +419,10 @@ describe('titreDemarcheUpdatedEtatValidate', () => { test('ajoute une demande en construction à une démarche vide', () => { const demarcheId = newDemarcheId() + const machineInfo = throwableMachineInfoForTestsOnly('axm', DEMARCHES_TYPES_IDS.Octroi, demarcheId, null) const valid = titreDemarcheUpdatedEtatValidate( - 'oct', - { - typeId: 'axm', - demarches: [{ id: demarcheId }], - }, + machineInfo, + [{ id: demarcheId }], { id: etapeIdValidator.parse('1'), typeId: ETAPES_TYPES.demande, @@ -480,7 +435,7 @@ describe('titreDemarcheUpdatedEtatValidate', () => { communes: [{ id: toCommuneId('97300') }], surface: km2Validator.parse(12), }, - demarcheId + [] ) expect(valid).toMatchInlineSnapshot(` @@ -493,12 +448,10 @@ describe('titreDemarcheUpdatedEtatValidate', () => { test('ajoute une demande en construction à une démarche qui contient déjà une étape', () => { const demarcheId = newDemarcheId() + const machineInfo = MachineInfo.withDate('axm', DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2020-01-01')) const valid = titreDemarcheUpdatedEtatValidate( - 'oct', - { - typeId: 'axm', - demarches: [{ id: demarcheId }], - }, + machineInfo, + [{ id: demarcheId }], { typeId: 'mfr', statutId: 'fai', @@ -508,8 +461,6 @@ describe('titreDemarcheUpdatedEtatValidate', () => { demarcheIdsConsentement: [], hasTitreFrom: true, }, - demarcheId, - [ { id: etapeIdValidator.parse('1'), @@ -530,12 +481,10 @@ describe('titreDemarcheUpdatedEtatValidate', () => { test('modifie une demande en construction à une démarche', () => { const demarcheId = newDemarcheId() + const machineInfo = MachineInfo.withDate('axm', DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2020-01-01')) const valid = titreDemarcheUpdatedEtatValidate( - 'oct', - { - typeId: 'axm', - demarches: [{ id: demarcheId }], - }, + machineInfo, + [{ id: demarcheId }], { id: etapeIdValidator.parse('1'), typeId: 'mfr', @@ -546,7 +495,6 @@ describe('titreDemarcheUpdatedEtatValidate', () => { hasTitreFrom: true, demarcheIdsConsentement: [], }, - demarcheId, [ { id: etapeIdValidator.parse('1'), @@ -578,13 +526,11 @@ describe('titreDemarcheUpdatedEtatValidate', () => { test('ne peut pas ajouter une 2ème demande en construction à une démarche', () => { const demarcheId = newDemarcheId() + const machineInfo = MachineInfo.withDate('axm', DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2024-01-01')) expect( titreDemarcheUpdatedEtatValidate( - 'oct', - { - typeId: 'axm', - demarches: [{ id: demarcheId }], - }, + machineInfo, + [{ id: demarcheId }], { typeId: 'mfr', statutId: 'fai', @@ -594,8 +540,6 @@ describe('titreDemarcheUpdatedEtatValidate', () => { demarcheIdsConsentement: [], hasTitreFrom: true, }, - demarcheId, - [ { id: etapeIdValidator.parse('1'), @@ -613,7 +557,7 @@ describe('titreDemarcheUpdatedEtatValidate', () => { ).toMatchInlineSnapshot(` { "errors": [ - "les étapes de la démarche machine AXMOct ne sont pas valides", + "les étapes de la démarche machine AncienLogigrammeOctroiAXM ne sont pas valides", ], "valid": false, } @@ -622,13 +566,11 @@ describe('titreDemarcheUpdatedEtatValidate', () => { test('ne peut pas ajouter une étape de type inconnu sur une machine', () => { const demarcheId = newDemarcheId() + const machineInfo = MachineInfo.withDate('axm', DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2021-01-01')) expect( titreDemarcheUpdatedEtatValidate( - 'oct', - { - typeId: 'axm', - demarches: [{ id: demarcheId }], - }, + machineInfo, + [{ id: demarcheId }], { typeId: 'aaa' as EtapeTypeId, date: toCaminoDate('2022-01-01'), @@ -641,8 +583,6 @@ describe('titreDemarcheUpdatedEtatValidate', () => { hasTitreFrom: true, demarcheIdsConsentement: [], }, - demarcheId, - [ { id: newEtapeId('1'), @@ -663,7 +603,7 @@ describe('titreDemarcheUpdatedEtatValidate', () => { ).toMatchInlineSnapshot(` { "errors": [ - "les étapes de la démarche machine AXMOct ne sont pas valides", + "les étapes de la démarche machine AncienLogigrammeOctroiAXM ne sont pas valides", ], "valid": false, } @@ -710,14 +650,17 @@ describe('getPossiblesEtapesTypes', () => { { typeId: 'apd', date: toCaminoDate('2024-03-19'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: newEtapeId(), ordre: 16, statutId: 'fre', communes: [] }, { typeId: 'app', date: toCaminoDate('2024-04-08'), isBrouillon: ETAPE_IS_NOT_BROUILLON, id: newEtapeId(), ordre: 17, statutId: 'def', communes: [] }, ] + const demarcheId = newDemarcheId() + const machineInfo = new ApiMachineInfo( + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2019-06-06')) + ) const tested = getPossiblesEtapesTypes( - undefined, - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + machineInfo, + ETAPES_TYPES.receptionDeComplements, rcoId, toCaminoDate('2019-06-06'), - etapes + etapes.map(etape => ({ ...etape, demarcheIdsConsentement: [] })) ) expect(tested.rco).toMatchInlineSnapshot(` @@ -817,9 +760,7 @@ describe('getPossiblesEtapesTypes', () => { expect( getPossiblesEtapesTypes( - new PrmOctMachine(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi), - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + new ApiMachineInfo(throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), 'AncienLogigrammeOctroiPRM')), ETAPES_TYPES.rapportEtAvisDeLaDREAL, apdId, toCaminoDate('2024-05-22'), @@ -921,9 +862,7 @@ describe('getPossiblesEtapesTypes', () => { expect( getPossiblesEtapesTypes( - new PrmOctMachine(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi), - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + new ApiMachineInfo(throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), 'AncienLogigrammeOctroiPRM')), ETAPES_TYPES.saisineDuPrefet, sppId, toCaminoDate('2023-05-03'), @@ -998,9 +937,7 @@ describe('getPossiblesEtapesTypes', () => { expect( getPossiblesEtapesTypes( - new PrmOctMachine(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi), - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + new ApiMachineInfo(throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), 'AncienLogigrammeOctroiPRM')), ETAPES_TYPES.enregistrementDeLaDemande, menId, toCaminoDate('2023-05-03'), @@ -1075,9 +1012,7 @@ describe('getPossiblesEtapesTypes', () => { expect( getPossiblesEtapesTypes( - new PrmOctMachine(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi), - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + new ApiMachineInfo(throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), 'AncienLogigrammeOctroiPRM')), ETAPES_TYPES.enregistrementDeLaDemande, menId, toCaminoDate('2023-06-01'), @@ -1089,7 +1024,15 @@ describe('getPossiblesEtapesTypes', () => { }) test('peut créer une étape sur une procédure spécifique vide', () => { - expect(getPossiblesEtapesTypes(new ProcedureSpecifiqueMachine('cxm', 'oct'), 'cxm', 'oct', undefined, undefined, toCaminoDate('4000-02-01'), [])).toMatchInlineSnapshot(` + expect( + getPossiblesEtapesTypes( + new ApiMachineInfo(throwableMachineInfoForTestsOnly('cxm', DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), 'ProcedureSpecifique')), + undefined, + undefined, + toCaminoDate('4000-02-01'), + [] + ) + ).toMatchInlineSnapshot(` { "mfr": { "etapeStatutIds": [ @@ -1375,9 +1318,11 @@ describe('getPossiblesEtapesTypes', () => { }, ] - const machine = new ArmOctMachine(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi) + const apiMachineInfoArmOct = new ApiMachineInfo( + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), 'AncienLogigrammeOctroiARM') + ) test('modifie une étape existante', () => { - const tested = getPossiblesEtapesTypes(machine, 'arm', 'oct', undefined, etapeIdValidator.parse('etapeId3'), toCaminoDate('2019-10-11'), etapes) + const tested = getPossiblesEtapesTypes(apiMachineInfoArmOct, undefined, etapeIdValidator.parse('etapeId3'), toCaminoDate('2019-10-11'), etapes) expect(Object.keys(tested)).toHaveLength(1) expect(tested.dae).toMatchInlineSnapshot(` { @@ -1390,13 +1335,13 @@ describe('getPossiblesEtapesTypes', () => { }) test.each(etapes)("modifie l'étape %# existante à la même date devrait permettre de recréer la même étape", etape => { - const etapesTypesPossibles = getPossiblesEtapesTypes(machine, 'arm', 'oct', etape.typeId, etape.id, etape.date, etapes) + const etapesTypesPossibles = getPossiblesEtapesTypes(apiMachineInfoArmOct, etape.typeId, etape.id, etape.date, etapes) expect(Object.keys(etapesTypesPossibles).length, `pas d'étapes possibles à l'étape ${JSON.stringify(etape)}. Devrait contenir AU MOINS la même étape`).toBeGreaterThan(0) expect(etapesTypesPossibles[etape.typeId]).toHaveProperty('etapeStatutIds') }) test('ajoute une nouvelle étape à la fin', () => { - const tested = getPossiblesEtapesTypes(machine, 'arm', 'oct', undefined, undefined, toCaminoDate('2022-05-06'), etapes) + const tested = getPossiblesEtapesTypes(apiMachineInfoArmOct, undefined, undefined, toCaminoDate('2022-05-06'), etapes) expect(Object.keys(tested)).toHaveLength(1) expect(tested.mnv).toMatchInlineSnapshot(` { @@ -1409,7 +1354,7 @@ describe('getPossiblesEtapesTypes', () => { }) test('ajoute une nouvelle étape en plein milieu', () => { - const tested = getPossiblesEtapesTypes(machine, 'arm', 'oct', undefined, undefined, toCaminoDate('2019-12-04'), etapes) + const tested = getPossiblesEtapesTypes(apiMachineInfoArmOct, undefined, undefined, toCaminoDate('2019-12-04'), etapes) expect(Object.keys(tested).toSorted()).toStrictEqual(['mca', 'mim', 'mod']) }) @@ -1451,7 +1396,7 @@ describe('getPossiblesEtapesTypes', () => { }, ] - const tested = getPossiblesEtapesTypes(machine, 'arm', 'oct', undefined, undefined, toCaminoDate('2019-12-04'), etapes) + const tested = getPossiblesEtapesTypes(apiMachineInfoArmOct, undefined, undefined, toCaminoDate('2019-12-04'), etapes) expect(Object.keys(tested).toSorted()).toStrictEqual(['dae', 'pfd', 'rde']) }) @@ -1493,7 +1438,7 @@ describe('getPossiblesEtapesTypes', () => { }, ] - const tested = getPossiblesEtapesTypes(machine, 'arm', 'oct', undefined, undefined, toCaminoDate('2019-12-04'), etapes) + const tested = getPossiblesEtapesTypes(apiMachineInfoArmOct, undefined, undefined, toCaminoDate('2019-12-04'), etapes) expect(Object.keys(tested)).toStrictEqual(['pfd']) }) @@ -1718,7 +1663,7 @@ describe('getPossiblesEtapesTypes', () => { }, ] - const tested = getPossiblesEtapesTypes(machine, 'arm', 'oct', undefined, undefined, toCaminoDate('2022-07-01'), etapes) + const tested = getPossiblesEtapesTypes(apiMachineInfoArmOct, undefined, undefined, toCaminoDate('2022-07-01'), etapes) expect(Object.keys(tested).toSorted()).toStrictEqual(['asc', 'css', 'des', 'mcb', 'mod', 'rcb', 'rde']) vi.resetAllMocks() }) @@ -1801,7 +1746,7 @@ describe('getPossiblesEtapesTypes', () => { }, ] - const tested = getPossiblesEtapesTypes(machine, 'arm', 'oct', undefined, undefined, toCaminoDate('2022-07-01'), etapes) + const tested = getPossiblesEtapesTypes(apiMachineInfoArmOct, undefined, undefined, toCaminoDate('2022-07-01'), etapes) expect(Object.keys(tested).toSorted()).toStrictEqual(['css', 'des', 'mcb', 'mcp', 'mod', 'rde']) }) @@ -1813,8 +1758,10 @@ describe('getPossiblesEtapesTypes', () => { surface: null, demarcheIdsConsentement: [], } as const - const procedureSpecifiqueMachine = new ProcedureSpecifiqueMachine('arm', 'oct') - test("peut éditer une mfr sur la procédure spécifique d'une démarche bien avancée", () => { + const apiMachineInfoSpecifique = new ApiMachineInfo( + throwableMachineInfoForTestsOnly(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(), 'ProcedureSpecifique') + ) + test("peut éditer une demande sur la procédure spécifique d'une démarche bien avancée", () => { const demandeId = newEtapeId('idMfr') const dateDemande = toCaminoDate('2024-12-01') const etapes: TitreEtapeForMachine[] = [ @@ -1869,15 +1816,7 @@ describe('getPossiblesEtapesTypes', () => { }, ] - const tested = getPossiblesEtapesTypes( - procedureSpecifiqueMachine, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, - ETAPES_TYPES.demande, - demandeId, - dateDemande, - etapes - ) + const tested = getPossiblesEtapesTypes(apiMachineInfoSpecifique, ETAPES_TYPES.demande, demandeId, dateDemande, etapes) expect(Object.keys(tested)).toStrictEqual([ETAPES_TYPES.demande]) }) diff --git a/packages/api/src/business/validations/titre-demarche-etat-validate.ts b/packages/api/src/business/validations/titre-demarche-etat-validate.ts index 74b86d705..c1cf09dce 100644 --- a/packages/api/src/business/validations/titre-demarche-etat-validate.ts +++ b/packages/api/src/business/validations/titre-demarche-etat-validate.ts @@ -1,19 +1,19 @@ // valide la date et la position de l'étape en fonction des autres étapes -import { NonEmptyArray, isNonEmptyArray, isNotNullNorUndefined, isNullOrUndefined, isNullOrUndefinedOrEmpty } from 'camino-common/src/typescript-tools' +import { NonEmptyArray, isNonEmptyArray, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, isNullOrUndefined, isNullOrUndefinedOrEmpty } from 'camino-common/src/typescript-tools' import type { ITitreEtape } from '../../types' import { Etape, TitreEtapeForMachine, titreEtapeForMachineValidator, toMachineEtapes } from '../rules-demarches/machine-common' -import { demarcheEnregistrementDemandeDateFind, DemarcheId } from 'camino-common/src/demarche' -import { DemarchesTypes, DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' import { ETAPE_IS_BROUILLON, ETAPE_IS_NOT_BROUILLON, EtapeId, EtapeTypeEtapeStatutWithMainStep } from 'camino-common/src/etape' -import { TitreTypeId } from 'camino-common/src/static/titresTypes' -import { CaminoMachines, machineFind } from '../rules-demarches/machines' +import { DemarcheId } from 'camino-common/src/demarche' +import { ApiMachineInfo, CaminoMachines, demarcheEnregistrementDemandeDateFind } from '../rules-demarches/machines' import { CaminoDate } from 'camino-common/src/date' import { EtapesTypes, EtapeTypeId } from 'camino-common/src/static/etapesTypes' import { titreEtapesSortAscByOrdre } from '../utils/titre-etapes-sort' import { getEtapesTDE, isTDEExist } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/index' import { etapeTypeDateFinCheck } from '../../api/_format/etapes-types' import { getEtapesStatuts } from 'camino-common/src/static/etapesTypesEtapesStatuts' +import { MachineInfo } from 'camino-common/src/machines' +import { DemarchesTypes } from 'camino-common/src/static/demarchesTypes' const titreDemarcheEtapesBuild = <T extends Pick<Partial<ITitreEtape>, 'id'>>(titreEtape: T, suppression: boolean, titreDemarcheEtapes?: T[] | null): T[] => { if (isNullOrUndefinedOrEmpty(titreDemarcheEtapes)) { @@ -46,14 +46,13 @@ const titreDemarcheEtapesBuild = <T extends Pick<Partial<ITitreEtape>, 'id'>>(ti // vérifie que la modification de la démarche // est valide par rapport aux définitions des types d'étape export const titreDemarcheUpdatedEtatValidate = ( - demarcheTypeId: DemarcheTypeId, - titre: { typeId: TitreTypeId; demarches?: { id: DemarcheId }[] }, + machineInfo: MachineInfo, + demarches: { id: DemarcheId }[], titreEtape: Pick<Partial<ITitreEtape>, 'id'> & Pick< ITitreEtape, 'statutId' | 'typeId' | 'date' | 'contenu' | 'surface' | 'communes' | 'isBrouillon' | 'hasTitreFrom' | 'concurrence' | 'demarcheIdsConsentement' | 'dateDebut' | 'dateFin' | 'duree' >, - demarcheId: DemarcheId, titreDemarcheEtapes?: | Pick< ITitreEtape, @@ -77,29 +76,27 @@ export const titreDemarcheUpdatedEtatValidate = ( suppression = false ): { valid: true; errors: null } | { valid: false; errors: NonEmptyArray<string> } => { const titreDemarcheEtapesNew = titreDemarcheEtapesBuild(titreEtape, suppression, titreDemarcheEtapes) - let machine: CaminoMachines | undefined - if (isNullOrUndefinedOrEmpty(titreDemarcheEtapesNew)) { - return { valid: true, errors: null } - } else { + let machine: ApiMachineInfo + if (isNotNullNorUndefinedNorEmpty(titreDemarcheEtapesNew)) { const firstEtapeDate = demarcheEnregistrementDemandeDateFind(titreDemarcheEtapesNew) - if (isNotNullNorUndefined(firstEtapeDate)) { - machine = machineFind(titre.typeId, demarcheTypeId, demarcheId, firstEtapeDate) - } + machine = new ApiMachineInfo(MachineInfo.withDate(machineInfo.titreTypeId, machineInfo.demarcheTypeId, machineInfo.demarcheId, firstEtapeDate)) + } else { + return { valid: true, errors: null } } const titreDemarchesErrors: string[] = [] // vérifie que la démarche existe dans le titre - if (!(titre.demarches?.some(({ id }) => id === demarcheId) ?? false)) { + if (!demarches.some(({ id }) => id === machineInfo.demarcheId)) { titreDemarchesErrors.push('le titre ne contient pas la démarche en cours de modification') } // on récupère tous les type d'étapes et les statuts associés applicable à la date souhaitée try { - const etapeTypesWithStatusPossibles = getPossiblesEtapesTypes(machine, titre.typeId, demarcheTypeId, titreEtape.typeId, titreEtape.id, titreEtape.date, titreDemarcheEtapes ?? []) + const etapeTypesWithStatusPossibles = getPossiblesEtapesTypes(machine, titreEtape.typeId, titreEtape.id, titreEtape.date, titreDemarcheEtapes ?? []) const statutPossiblesPourCetteEtape = etapeTypesWithStatusPossibles[titreEtape.typeId] if (isNullOrUndefined(statutPossiblesPourCetteEtape) || !statutPossiblesPourCetteEtape.etapeStatutIds.includes(titreEtape.statutId)) { - if (isNotNullNorUndefined(machine)) { - return { valid: false, errors: [`les étapes de la démarche machine ${machine.machine.id} ne sont pas valides`] } + if (isNotNullNorUndefined(machine.machine)) { + return { valid: false, errors: [`les étapes de la démarche machine ${machine.machineId} ne sont pas valides`] } } else { return { valid: false, errors: ['les étapes de la démarche TDE ne sont pas valides'] } } @@ -109,11 +106,11 @@ export const titreDemarcheUpdatedEtatValidate = ( titreDemarchesErrors.push(e.message) } - if (isNotNullNorUndefined(machine)) { + if (isNotNullNorUndefined(machine.machine)) { // vérifie que toutes les étapes existent dans l’arbre try { - const ok = machine.isEtapesOk( - machine.orderMachine( + const ok = machine.machine.isEtapesOk( + machine.machine.orderMachine( toMachineEtapes( titreDemarcheEtapesNew.map(etape => ({ ...etape, @@ -143,30 +140,28 @@ export const titreDemarcheUpdatedEtatValidate = ( } export const getPossiblesEtapesTypes = ( - machine: CaminoMachines | undefined, - titreTypeId: TitreTypeId, - demarcheTypeId: DemarcheTypeId, + machine: ApiMachineInfo, etapeTypeId: EtapeTypeId | undefined, etapeId: EtapeId | undefined, date: CaminoDate, demarcheEtapes: Pick<ITitreEtape, 'typeId' | 'date' | 'isBrouillon' | 'id' | 'ordre' | 'statutId' | 'communes'>[] ): EtapeTypeEtapeStatutWithMainStep => { let etapesTypes: EtapeTypeEtapeStatutWithMainStep = {} - if (isNotNullNorUndefined(machine)) { + if (isNotNullNorUndefined(machine.machine)) { const etapes = demarcheEtapes.map(etape => titreEtapeForMachineValidator.parse(etape)) - etapesTypes = etapesTypesPossibleACetteDateOuALaPlaceDeLEtape(machine, etapes, etapeId ?? null, date) + etapesTypes = etapesTypesPossibleACetteDateOuALaPlaceDeLEtape(machine.machine, etapes, etapeId ?? null, date) } else { // si on modifie une étape // vérifie que son type est possible sur la démarche if (isNotNullNorUndefined(etapeTypeId)) { - if (!isTDEExist(titreTypeId, demarcheTypeId, etapeTypeId)) { - const demarcheType = DemarchesTypes[demarcheTypeId] - throw new Error(`étape ${EtapesTypes[etapeTypeId].nom} inexistante pour une démarche ${demarcheType.nom} pour un titre ${titreTypeId}.`) + if (!isTDEExist(machine.titreTypeId, machine.demarcheTypeId, etapeTypeId)) { + const demarcheType = DemarchesTypes[machine.demarcheTypeId] + throw new Error(`étape ${EtapesTypes[etapeTypeId].nom} inexistante pour une démarche ${demarcheType.nom} pour un titre ${machine.titreTypeId}.`) } } // dans un premier temps on récupère toutes les étapes possibles pour cette démarche - let etapesTypesTDE = getEtapesTDE(titreTypeId, demarcheTypeId) + let etapesTypesTDE = getEtapesTDE(machine.titreTypeId, machine.demarcheTypeId) const etapeTypesExistants = demarcheEtapes.map(({ typeId }) => typeId) etapesTypesTDE = etapesTypesTDE diff --git a/packages/api/src/business/validations/titre-etape-updation-validate.test.ts b/packages/api/src/business/validations/titre-etape-updation-validate.test.ts index f6a04ad71..89bbb7a3c 100644 --- a/packages/api/src/business/validations/titre-etape-updation-validate.test.ts +++ b/packages/api/src/business/validations/titre-etape-updation-validate.test.ts @@ -10,6 +10,7 @@ import { entrepriseIdValidator } from 'camino-common/src/entreprise' import { titreIdValidator } from 'camino-common/src/validators/titres' import { km2Validator } from 'camino-common/src/number' import { ApiFlattenEtape } from '../../api/_format/titres-etapes' +import { MachineInfo } from 'camino-common/src/machines' const etapeBrouillonValide: Omit<ApiFlattenEtape, 'id'> = { titulaires: { value: [], @@ -68,10 +69,13 @@ const etapeComplete: Omit<ApiFlattenEtape, 'id'> = { contenu: { arm: { mecanise: { value: true, heritee: true, etapeHeritee: { date: toCaminoDate('2022-01-01'), etapeTypeId: 'mfr', value: true } } } }, } const demarcheId = demarcheIdValidator.parse('demarcheId') +const machineInfoARM = MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDateValidator.parse('2022-01-01')) +const machineInfoAXM = MachineInfo.withDate('axm', 'oct', demarcheId, firstEtapeDateValidator.parse('2022-01-01')) const titreDemarche: ITitreDemarche = { id: demarcheId, typeId: 'oct', titreId: titreIdValidator.parse('titreId'), + machineId: machineInfoARM.machineId ?? null, etapes: [ { date: toCaminoDate('2022-01-01'), @@ -149,7 +153,7 @@ describe('valide l’étape avant de l’enregistrer', () => { demarcheIdsConsentement: [], } - let errors = titreEtapeUpdationValidate(titreEtape, titreDemarche, titreARM, [], [], [], [], [], userSuper, firstEtapeDateValidator.parse('2022-01-01')) + let errors = titreEtapeUpdationValidate(titreEtape, titreDemarche.etapes ?? [], titreARM.demarches ?? [], [], [], [], [], [], userSuper, machineInfoARM) expect(errors).toMatchInlineSnapshot(` [ "une date peut-être spécifiée que sur une étape de décision", @@ -164,12 +168,8 @@ describe('valide l’étape avant de l’enregistrer', () => { "Il y a des documents d'entreprise obligatoires, mais il n'y a pas de titulaire", ] `) - // AXM - const titreAxm: Pick<ITitre, 'typeId'> = { - typeId: 'axm', - } - errors = titreEtapeUpdationValidate(titreEtape, titreDemarche, titreAxm, [], [], [], [], [], userSuper, firstEtapeDateValidator.parse('2022-01-01')) + errors = titreEtapeUpdationValidate(titreEtape, titreDemarche.etapes ?? [], [titreDemarche], [], [], [], [], [], userSuper, machineInfoAXM) expect(errors).toMatchInlineSnapshot(` [ "une date peut-être spécifiée que sur une étape de décision", @@ -190,11 +190,11 @@ describe('valide l’étape avant de l’enregistrer', () => { `) }) test('valide brouillon', () => { - const errors = titreEtapeUpdationValidate(etapeBrouillonValide, { ...titreDemarche, etapes: [] }, titreARM, [], [], [], [], [], userSuper, firstEtapeDateValidator.parse('2022-01-01')) + const errors = titreEtapeUpdationValidate(etapeBrouillonValide, [], [{ ...titreDemarche, etapes: [] }], [], [], [], [], [], userSuper, machineInfoARM) expect(errors).toStrictEqual([]) }) test('valide complète', () => { - const errors = titreEtapeUpdationValidate(etapeComplete, titreDemarche, titreARM, [{ etape_document_type_id: 'doe' }], [], [], [], [], userSuper, firstEtapeDateValidator.parse('2022-01-01')) + const errors = titreEtapeUpdationValidate(etapeComplete, titreDemarche.etapes ?? [], titreARM.demarches ?? [], [{ etape_document_type_id: 'doe' }], [], [], [], [], userSuper, machineInfoARM) expect(errors).toStrictEqual([]) }) test('invalide car on ne peut pas faire de mod sans men', () => { @@ -219,19 +219,19 @@ describe('valide l’étape avant de l’enregistrer', () => { etapeHeritee: null, }, }, - titreDemarche, - titreARM, + titreDemarche.etapes ?? [], + titreARM.demarches ?? [], [{ etape_document_type_id: 'doe' }], [], [], [], [], userSuper, - firstEtapeDateValidator.parse('2022-01-01') + machineInfoARM ) expect(errors).toMatchInlineSnapshot(` [ - "les étapes de la démarche machine octArm ne sont pas valides", + "les étapes de la démarche machine AncienLogigrammeOctroiARM ne sont pas valides", ] `) }) @@ -239,30 +239,30 @@ describe('valide l’étape avant de l’enregistrer', () => { test('valide complète avec héritage', () => { const errors = titreEtapeUpdationValidate( { ...etapeComplete, duree: { value: 12, heritee: true, etapeHeritee: { date: toCaminoDate('2022-01-01'), etapeTypeId: 'mfr', value: 12 } } }, - titreDemarche, - titreARM, + titreDemarche.etapes ?? [], + titreARM.demarches ?? [], [{ etape_document_type_id: 'doe' }], [], [], [], [], userSuper, - firstEtapeDateValidator.parse('2022-01-01') + machineInfoARM ) expect(errors).toStrictEqual([]) }) test('ne peut pas éditer les amodiataires sur une ARM', () => { const errors = titreEtapeUpdationValidate( { ...etapeComplete, amodiataires: { value: [entrepriseIdValidator.parse('entrepriseIdAmodiataire')], heritee: false, etapeHeritee: null } }, - titreDemarche, - titreARM, + titreDemarche.etapes ?? [], + titreARM.demarches ?? [], [{ etape_document_type_id: 'doe' }], [], [], [], [], userSuper, - firstEtapeDateValidator.parse('2022-01-01') + machineInfoARM ) expect(errors).toMatchInlineSnapshot(` [ diff --git a/packages/api/src/business/validations/titre-etape-updation-validate.ts b/packages/api/src/business/validations/titre-etape-updation-validate.ts index eba3f8716..2932ca067 100644 --- a/packages/api/src/business/validations/titre-etape-updation-validate.ts +++ b/packages/api/src/business/validations/titre-etape-updation-validate.ts @@ -1,4 +1,4 @@ -import { ITitreEtape, ITitreDemarche, ITitre } from '../../types' +import { ITitreEtape, ITitreDemarche } from '../../types' import { titreDemarcheUpdatedEtatValidate } from './titre-demarche-etat-validate' import { contenuNumbersCheck } from './utils/contenu-numbers-check' @@ -14,32 +14,33 @@ import { isNotNullNorUndefined, isNullOrUndefined } from 'camino-common/src/type import { flattenContenuToSimpleContenu } from 'camino-common/src/sections' import { equalGeojson } from 'camino-common/src/perimetre' import { ApiFlattenEtape } from '../../api/_format/titres-etapes' -import { FirstEtapeDate } from 'camino-common/src/date' +import { MachineInfo } from 'camino-common/src/machines' +import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' export const titreEtapeUpdationValidate = ( etape: Pick<Partial<ApiFlattenEtape>, 'id'> & Omit<ApiFlattenEtape, 'id'>, - titreDemarche: ITitreDemarche, - titre: Pick<ITitre, 'typeId' | 'demarches'>, + etapes: ITitreEtape[], + demarches: ITitreDemarche[], documents: Pick<EtapeDocument, 'etape_document_type_id'>[], etapeAvis: Pick<EtapeAvis, 'avis_type_id'>[], entrepriseDocuments: Pick<EntrepriseDocument, 'entreprise_document_type_id' | 'entreprise_id'>[], sdomZones: SDOMZoneId[] | null | undefined, communes: CommuneId[] | null | undefined, user: User, - firstEtapeDate: FirstEtapeDate, + machineInfo: MachineInfo, titreEtapeOld?: ITitreEtape ): string[] => { const errors: string[] = [] - const sections = getSections(titre.typeId, titreDemarche.typeId, etape.typeId) + const sections = getSections(machineInfo, etape.typeId) if (!etape.duree.heritee) { - const editDuree = canEditDuree(titre.typeId, titreDemarche.typeId, user) + const editDuree = canEditDuree(machineInfo, user) if (editDuree.visibility === 'absent' && (etape.duree.value ?? 0) !== (titreEtapeOld?.duree ?? 0)) { errors.push(editDuree.message) } } - const editDates = canEditDates(titre.typeId, titreDemarche.typeId, etape.typeId, user) + const editDates = canEditDates(machineInfo, etape.typeId, user) if (editDates.visibility === 'absent') { if (!etape.dateDebut.heritee && (etape.dateDebut.value ?? '') !== (titreEtapeOld?.dateDebut ?? '')) { errors.push(editDates.message) @@ -49,21 +50,21 @@ export const titreEtapeUpdationValidate = ( } if (!etape.titulaires.heritee) { - const editTitulaires = canEditTitulaires(titre.typeId, titreDemarche.typeId, user) + const editTitulaires = canEditTitulaires(machineInfo, user) if (editTitulaires.visibility === 'absent' && entreprisesHaveChanged(etape.titulaires.value, titreEtapeOld?.titulaireIds ?? [])) { errors.push(editTitulaires.message) } } if (!etape.amodiataires.heritee) { - const editAmodiataires = canEditAmodiataires(titre.typeId, titreDemarche.typeId, user) + const editAmodiataires = canEditAmodiataires(machineInfo, user) if (editAmodiataires.visibility === 'absent' && entreprisesHaveChanged(etape.amodiataires.value, titreEtapeOld?.amodiataireIds ?? [])) { errors.push(editAmodiataires.message) } } if (!etape.perimetre.heritee) { - const editPerimetre = canEditPerimetre(titreDemarche.typeId, etape.typeId) + const editPerimetre = canEditPerimetre(machineInfo, etape.typeId) if (editPerimetre.visibility === 'absent' && !equalGeojson(etape.perimetre.value?.geojson4326Perimetre?.geometry ?? null, titreEtapeOld?.geojson4326Perimetre?.geometry)) { errors.push(editPerimetre.message) } @@ -85,7 +86,7 @@ export const titreEtapeUpdationValidate = ( } if ( - etape.typeId !== 'mfr' && + etape.typeId !== ETAPES_TYPES.demande && isNotNullNorUndefined(etape.contenu.arm?.mecanise) && etape.contenu.arm.mecanise.value === true && !etape.contenu.arm.mecanise.heritee && @@ -95,14 +96,14 @@ export const titreEtapeUpdationValidate = ( } } - const etapeValid = isEtapeValid(etape, titre.typeId, titreDemarche.typeId, titreDemarche.id, firstEtapeDate) + const etapeValid = isEtapeValid(etape, machineInfo) if (!etapeValid.valid) { errors.push(...etapeValid.errors) } // si l’étape n’est pas en cours de construction if (etape.isBrouillon === ETAPE_IS_NOT_BROUILLON) { - const etapeComplete = isEtapeComplete(etape, titre.typeId, titreDemarche.id, titreDemarche.typeId, documents, entrepriseDocuments, sdomZones, communes ?? [], etapeAvis, user, firstEtapeDate) + const etapeComplete = isEtapeComplete(etape, machineInfo, documents, entrepriseDocuments, sdomZones, communes ?? [], etapeAvis, user) if (!etapeComplete.valid) { errors.push(...etapeComplete.errors) } @@ -112,30 +113,30 @@ export const titreEtapeUpdationValidate = ( return errors } - return titreEtapeUpdationBusinessValidate(etape, titreDemarche, titre, isNotNullNorUndefined(communes) ? communes.map(communeId => ({ id: communeId })) : communes) + return titreEtapeUpdationBusinessValidate(etape, etapes, demarches, isNotNullNorUndefined(communes) ? communes.map(communeId => ({ id: communeId })) : communes, machineInfo) } const titreEtapeUpdationBusinessValidate = ( titreEtape: Pick<Partial<ApiFlattenEtape>, 'id'> & Pick<ApiFlattenEtape, 'statutId' | 'typeId' | 'date' | 'contenu' | 'perimetre' | 'isBrouillon' | 'concurrence' | 'demarcheIdsConsentement' | 'hasTitreFrom'>, - titreDemarche: ITitreDemarche, - titre: Pick<ITitre, 'typeId' | 'demarches'>, - communes: ITitreEtape['communes'] + etapes: ITitreEtape[], + demarches: ITitreDemarche[], + communes: ITitreEtape['communes'], + machineInfo: MachineInfo ) => { const errors = [] // 1. la date de l'étape est possible // en fonction de l'ordre des types d'étapes de la démarche const { valid, errors: demarcheUpdatedErrors } = titreDemarcheUpdatedEtatValidate( - titreDemarche.typeId, - titre, + machineInfo, + demarches, { ...titreEtape, contenu: flattenContenuToSimpleContenu(titreEtape.contenu), surface: titreEtape.perimetre.value?.surface ?? null, communes, }, - titreDemarche.id, - titreDemarche.etapes! + etapes ) if (!valid) { errors.push(...demarcheUpdatedErrors) diff --git a/packages/api/src/database/models/titres-demarches.ts b/packages/api/src/database/models/titres-demarches.ts index 7513cc7ef..e8006319d 100644 --- a/packages/api/src/database/models/titres-demarches.ts +++ b/packages/api/src/database/models/titres-demarches.ts @@ -30,6 +30,7 @@ class TitresDemarches extends Model { description: { type: ['string', 'null'] }, demarcheDateDebut: { type: ['string', 'null'] }, demarcheDateFin: { type: ['string', 'null'] }, + machineId: { type: ['string', 'null'] }, archive: { type: 'boolean' }, }, } diff --git a/packages/api/src/database/queries/permissions/titres.test.integration.ts b/packages/api/src/database/queries/permissions/titres.test.integration.ts index f4622e57f..b22bc06e4 100644 --- a/packages/api/src/database/queries/permissions/titres.test.integration.ts +++ b/packages/api/src/database/queries/permissions/titres.test.integration.ts @@ -13,11 +13,12 @@ import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' import { DemarcheStatutId } from 'camino-common/src/static/demarchesStatuts' import { EtapeStatutId } from 'camino-common/src/static/etapesStatuts' import { EtapeTypeId } from 'camino-common/src/static/etapesTypes' -import { toCaminoDate } from 'camino-common/src/date' +import { firstEtapeDateValidator, toCaminoDate } from 'camino-common/src/date' import { entrepriseIdValidator } from 'camino-common/src/entreprise' import TitresDemarches from '../../models/titres-demarches' import TitresEtapes from '../../models/titres-etapes' import { ETAPE_IS_NOT_BROUILLON } from 'camino-common/src/etape' +import { MachineInfo } from 'camino-common/src/machines' console.info = vi.fn() console.error = vi.fn() @@ -58,6 +59,7 @@ describe('titresQueryModify', () => { { id: demarcheId, typeId: 'oct', + machineId: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDateValidator.parse('2020-01-01')).machineId ?? null, }, { id: etapeId, @@ -99,6 +101,7 @@ describe('titresQueryModify', () => { { id: demarcheId, typeId: 'oct', + machineId: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDateValidator.parse('2020-01-01')).machineId ?? null, }, { id: etapeId, @@ -154,6 +157,7 @@ describe('titresQueryModify', () => { id: demarcheId, typeId: demarcheTypeId, statutId: demarcheStatutId, + machineId: MachineInfo.withDate(titreTypeId, demarcheTypeId, demarcheId, firstEtapeDateValidator.parse('2020-01-01')).machineId ?? null, }, { id: etapeId, @@ -240,6 +244,7 @@ describe('titresQueryModify', () => { id: demarcheId, typeId: 'oct', statutId: 'ins', + machineId: MachineInfo.withDate(typeId, 'oct', demarcheId, firstEtapeDateValidator.parse('2020-01-01')).machineId ?? null, }, { id: etapeId, diff --git a/packages/api/src/database/queries/titres-demarches.ts b/packages/api/src/database/queries/titres-demarches.ts index b39e23155..063976b4f 100644 --- a/packages/api/src/database/queries/titres-demarches.ts +++ b/packages/api/src/database/queries/titres-demarches.ts @@ -314,13 +314,6 @@ export const titreDemarcheGet = async (titreDemarcheId: string, { fields }: { fi .first() } -/** - * Crée une nouvelle démarche - * @param titreDemarche - démarche à créer - * @returns la nouvelle démarche - */ -export const titreDemarcheCreate = async (titreDemarche: Omit<ITitreDemarche, 'id'>): Promise<ITitreDemarche> => TitresDemarches.query().insertAndFetch(titreDemarche) - export const titreDemarcheUpdate = async (id: DemarcheId, titreDemarche: Partial<DBTitresDemarches>): Promise<TitresDemarches> => { return TitresDemarches.query().patchAndFetchById(id, { ...titreDemarche, id }) } diff --git a/packages/api/src/database/queries/titres-etapes.queries.ts b/packages/api/src/database/queries/titres-etapes.queries.ts index ad17f2727..e4ca1e402 100644 --- a/packages/api/src/database/queries/titres-etapes.queries.ts +++ b/packages/api/src/database/queries/titres-etapes.queries.ts @@ -53,7 +53,7 @@ import { TitreTypeId, titreTypeIdValidator } from 'camino-common/src/static/titr import { isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, SimplePromiseFn } from 'camino-common/src/typescript-tools' import { CanReadDemarche } from '../../api/rest/permissions/demarches' import { newEtapeAvisId, newEtapeDocumentId } from '../models/_format/id-create' -import { caminoDateValidator, FirstEtapeDate, getCurrent } from 'camino-common/src/date' +import { caminoDateValidator, getCurrent } from 'camino-common/src/date' import { createLargeObject, CreateLargeObjectError, LargeObjectId, largeObjectIdValidator } from '../largeobjects' import { avisStatutIdValidator, avisVisibilityIdValidator } from 'camino-common/src/static/avisTypes' import { canReadAvis } from '../../api/rest/permissions/avis' @@ -62,13 +62,15 @@ import { etapeAvisStepIsComplete } from 'camino-common/src/permissions/etape-for import { CommuneId } from 'camino-common/src/static/communes' import { EtapeStatutId, etapeStatutIdValidator } from 'camino-common/src/static/etapesStatuts' import { contenuValidator, FlattenedContenu, heritageContenuValidator } from 'camino-common/src/etape-form' -import { DemarcheTypeId, demarcheTypeIdValidator } from 'camino-common/src/static/demarchesTypes' +import { demarcheTypeIdValidator } from 'camino-common/src/static/demarchesTypes' import { Effect, Option, pipe } from 'effect' import { CaminoError } from 'camino-common/src/zod-tools' import { callAndExit, shortCircuitError, zodParseEffectTyped } from '../../tools/fp-tools' import { TempDocumentName } from 'camino-common/src/document' -import { DemarcheId } from 'camino-common/src/demarche' import { autreDocumentTypeIdValidator, documentTypeIdValidator, isAutreDocument } from 'camino-common/src/static/documentsTypes' +import { MachineInfo } from 'camino-common/src/machines' +import { machineIdValidator } from 'camino-common/src/validators/machine' +import { demarcheIdValidator } from 'camino-common/src/demarche' export const insertTitreEtapeEntrepriseDocuments = ( pool: Pool, @@ -310,17 +312,12 @@ export const updateEtapeAvis = ( etapeAvis: EtapeAvisModification[], etapeTypeId: EtapeTypeId, etapeContenu: FlattenedContenu, - titreTypeId: TitreTypeId, - demarcheTypeId: DemarcheTypeId, - demarcheId: DemarcheId, - firstEtapeDate: FirstEtapeDate, + machineInfo: MachineInfo, communeIds: CommuneId[] ): Effect.Effect<Option.Option<never>, CaminoError<UpdateEtapeAvisErrors>> => { return Effect.Do.pipe( Effect.filterOrFail( - () => - isBrouillon === ETAPE_IS_BROUILLON || - etapeAvisStepIsComplete({ typeId: etapeTypeId, contenu: etapeContenu }, etapeAvis, titreTypeId, demarcheTypeId, demarcheId, firstEtapeDate, communeIds).valid, + () => isBrouillon === ETAPE_IS_BROUILLON || etapeAvisStepIsComplete({ typeId: etapeTypeId, contenu: etapeContenu }, etapeAvis, machineInfo, communeIds).valid, () => ({ message: avisIncomplets }) ), Effect.bind('avisInDb', () => effectDbQueryAndValidate(getAvisByEtapeIdQuery, { titre_etape_id }, pool, etapeAvisDbValidator)), @@ -595,6 +592,8 @@ const getEtapesWithAutomaticStatutValidator = z.object({ heritage_contenu: heritageContenuValidator, titre_type_id: titreTypeIdValidator, demarche_type_id: demarcheTypeIdValidator, + demarche_machine_id: machineIdValidator.nullable(), + demarche_id: demarcheIdValidator, }) type GetEtapesWithAutomaticStatutQuery = z.infer<typeof getEtapesWithAutomaticStatutValidator> @@ -611,7 +610,9 @@ const getEtapesWithAutomaticStatutDb = sql<Redefine<IGetEtapesWithAutomaticStatu te.statut_id as etape_statut_id, te.date, t.type_id as titre_type_id, - td.type_id as demarche_type_id + td.type_id as demarche_type_id, + td.machine_id as demarche_machine_id, + td.id as demarche_id from titres_etapes te join titres_demarches td on te.titre_demarche_id = td.id join titres t on td.titre_id = t.id diff --git a/packages/api/src/database/queries/titres-etapes.queries.types.ts b/packages/api/src/database/queries/titres-etapes.queries.types.ts index 80db6b69d..cd3e4166c 100644 --- a/packages/api/src/database/queries/titres-etapes.queries.types.ts +++ b/packages/api/src/database/queries/titres-etapes.queries.types.ts @@ -276,6 +276,8 @@ export interface IGetEtapesWithAutomaticStatutDbParams { export interface IGetEtapesWithAutomaticStatutDbResult { contenu: Json | null; date: string; + demarche_id: string; + demarche_machine_id: string | null; demarche_type_id: string; etape_statut_id: string; heritage_contenu: Json | null; diff --git a/packages/api/src/database/queries/titres-utilisateurs.queries.ts b/packages/api/src/database/queries/titres-utilisateurs.queries.ts index 2f8d32faa..fc828cbd9 100644 --- a/packages/api/src/database/queries/titres-utilisateurs.queries.ts +++ b/packages/api/src/database/queries/titres-utilisateurs.queries.ts @@ -29,6 +29,7 @@ select t.titre_statut_id, td.type_id as demarche_type_id, td.slug as demarche_slug, + td.machine_id as machine_id, te.type_id as etape_type_id, te.slug as etape_slug, te.date as etape_date diff --git a/packages/api/src/database/queries/titres-utilisateurs.queries.types.ts b/packages/api/src/database/queries/titres-utilisateurs.queries.types.ts index 991b82f34..b6e8f64fc 100644 --- a/packages/api/src/database/queries/titres-utilisateurs.queries.types.ts +++ b/packages/api/src/database/queries/titres-utilisateurs.queries.types.ts @@ -10,6 +10,7 @@ export interface IGetTitresWithBrouillonsDbResult { etape_date: string; etape_slug: string | null; etape_type_id: string; + machine_id: string | null; titre_nom: string; titre_slug: string; titre_statut_id: string; diff --git a/packages/api/src/knex/migrations/20250325135645_add-column-machine-to-demarches.ts b/packages/api/src/knex/migrations/20250325135645_add-column-machine-to-demarches.ts new file mode 100644 index 000000000..7c5203c78 --- /dev/null +++ b/packages/api/src/knex/migrations/20250325135645_add-column-machine-to-demarches.ts @@ -0,0 +1,49 @@ +import { Knex } from 'knex' +import type { DemarcheId } from 'camino-common/src/demarche' +import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' +import type { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' +import type { TitreTypeId } from 'camino-common/src/static/titresTypes' +import type { FirstEtapeDate } from 'camino-common/src/date' +import { isNotNullNorUndefined } from 'camino-common/src/typescript-tools' +import { MachineInfo } from 'camino-common/src/machines' + +export const up = async (knex: Knex): Promise<void> => { + await knex.raw('ALTER TABLE titres_demarches ADD COLUMN machine_id VARCHAR') + await knex.raw('CREATE INDEX titres_demarches_machine_id_index ON titres_demarches USING btree (machine_id)') + + const demarches: { rows: { id: DemarcheId; demarche_type_id: DemarcheTypeId; titre_type_id: TitreTypeId }[] } = await knex.raw( + `select td.id, td.type_id as demarche_type_id, t.type_id as titre_type_id from titres_demarches td join titres t on t.id = td.titre_id where td.archive is false` + ) + for (const demarche of demarches.rows) { + const firstEtapeDate: { + rows: { first_etape_date: FirstEtapeDate }[] + } = await knex.raw( + ` + select + te.date as first_etape_date + from + titres_demarches td + left join titres_etapes te on te.titre_demarche_id = td.id AND (te.type_id = :enregistrementDeLaDemandeId OR te.ordre = 1) AND te.archive IS FALSE + where (td.id = :idOrSlug + or td.slug = :idOrSlug) + and td.archive is false + order by te.ordre desc + LIMIT 1 + `, + { + enregistrementDeLaDemandeId: ETAPES_TYPES.enregistrementDeLaDemande, + idOrSlug: demarche.id, + } + ) + + if (firstEtapeDate.rows.length === 1 && isNotNullNorUndefined(firstEtapeDate.rows[0].first_etape_date)) { + const machineId = MachineInfo.withDate(demarche.titre_type_id, demarche.demarche_type_id, demarche.id, firstEtapeDate.rows[0].first_etape_date) + await knex.raw('UPDATE titres_demarches SET machine_id = :machineId WHERE id = :id', { + id: demarche.id, + machineId: isNotNullNorUndefined(machineId.machineId) ? machineId.machineId : null, + }) + } + } +} + +export const down = (): void => {} diff --git a/packages/api/src/pg-database.ts b/packages/api/src/pg-database.ts index 2767a3216..bc655a750 100644 --- a/packages/api/src/pg-database.ts +++ b/packages/api/src/pg-database.ts @@ -4,8 +4,8 @@ import type { Pool } from 'pg' import { z } from 'zod' import type { ZodType, ZodTypeDef } from 'zod' import { CaminoError } from 'camino-common/src/zod-tools' -import { zodParseEffect } from './tools/fp-tools' -import { Effect, Match, pipe } from 'effect' +import { zodParseEffectTyped } from './tools/fp-tools' +import { Effect, pipe } from 'effect' export type Redefine<T, P, O> = T extends { params: infer A; result: infer B } ? { inputs: keyof A; outputs: keyof B } extends { inputs: keyof P; outputs: keyof O } ? { inputs: keyof P; outputs: keyof O } extends { inputs: keyof A; outputs: keyof B } @@ -15,7 +15,7 @@ export type Redefine<T, P, O> = T extends { params: infer A; result: infer B } : { __camino_error: 'on a pas params et result' } /** - * @deprecated use newDbQueryAndValidate + * @deprecated use effectDbQueryAndValidate */ export const dbQueryAndValidate = async <Params, Result, T extends ZodType<Result, ZodTypeDef, unknown>>( query: TaggedQuery<{ params: Params; result: Result }>, @@ -53,15 +53,6 @@ export const effectDbQueryAndValidate = <Params, Result, T extends ZodType<Resul return { message: "Impossible d'exécuter la requête dans la base de données" as const, extra } }, }), - Effect.flatMap(result => - zodParseEffect(z.array(validator), result).pipe( - Effect.mapError(caminoError => - Match.value(caminoError.message).pipe( - Match.when('Problème de validation de données', () => ({ ...caminoError, message: 'Les données en base ne correspondent pas à ce qui est attendu' as const })), - Match.exhaustive - ) - ) - ) - ) + Effect.flatMap(result => zodParseEffectTyped(z.array(validator), result, 'Les données en base ne correspondent pas à ce qui est attendu' as const)) ) } diff --git a/packages/api/src/tools/demarches/definitions-check.ts b/packages/api/src/tools/demarches/definitions-check.ts index 384407292..93087d64f 100644 --- a/packages/api/src/tools/demarches/definitions-check.ts +++ b/packages/api/src/tools/demarches/definitions-check.ts @@ -4,7 +4,7 @@ import { userSuper } from '../../database/user-super' import { getTitreTypeType, getDomaineId } from 'camino-common/src/static/titresTypes' import { isNotNullNorUndefinedNorEmpty, onlyUnique } from 'camino-common/src/typescript-tools' import { DemarcheId } from 'camino-common/src/demarche' -import { demarchesDefinitions } from 'camino-common/src/machines' +import { demarchesDefinitions, MachineInfo } from 'camino-common/src/machines' const demarchesValidate = async () => { const demarchesIdsAlreadyChecked: Set<DemarcheId> = new Set() @@ -32,7 +32,12 @@ const demarchesValidate = async () => { if (isNotNullNorUndefinedNorEmpty(demarche.etapes)) { try { const sortedEtapes = demarche.etapes!.toSorted((a, b) => (a.ordre ?? 0) - (b.ordre ?? 0)) - const { valid, errors } = titreDemarcheUpdatedEtatValidate(demarche.typeId, demarche.titre!, sortedEtapes![0], demarche.id, sortedEtapes!) + const machineInfo = MachineInfo.withMachineId(demarche.titre!.typeId, demarche.typeId, demarche.id, demarche.machineId) + if (!machineInfo.valid) { + throw new Error(`La machine associée à la démarche est incohérente : ${machineInfo.error}`) + } + + const { valid, errors } = titreDemarcheUpdatedEtatValidate(machineInfo.value, demarche.titre!.demarches!, sortedEtapes![0], sortedEtapes!) if (!valid) { errorsTotal.push(`https://camino.beta.gouv.fr/demarches/${demarche.slug} => démarche "${demarche.typeId}" : ${errors}`) diff --git a/packages/api/src/tools/demarches/tde-check.ts b/packages/api/src/tools/demarches/tde-check.ts index 5dc63a883..7b710da23 100644 --- a/packages/api/src/tools/demarches/tde-check.ts +++ b/packages/api/src/tools/demarches/tde-check.ts @@ -2,9 +2,7 @@ import { EtapesTypes } from 'camino-common/src/static/etapesTypes' import { isTDEExist } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/index' import { titresDemarchesGet } from '../../database/queries/titres-demarches' import { userSuper } from '../../database/user-super' -import { isNotNullNorUndefined, isNullOrUndefined } from 'camino-common/src/typescript-tools' -import { CaminoMachineId, machineIdFind } from 'camino-common/src/machines' -import { demarcheEnregistrementDemandeDateFind } from 'camino-common/src/demarche' +import { isNullOrUndefined } from 'camino-common/src/typescript-tools' export const titreTypeDemarcheTypeEtapeTypeCheck = async (): Promise<number> => { console.info() @@ -26,13 +24,7 @@ export const titreTypeDemarcheTypeEtapeTypeCheck = async (): Promise<number> => let errorsNb = 0 demarches.forEach(d => { - const firstEtapeDate = demarcheEnregistrementDemandeDateFind(d.etapes) - let machineId: CaminoMachineId | undefined - if (isNotNullNorUndefined(firstEtapeDate)) { - machineId = machineIdFind(d.titre!.typeId, d.typeId, d.id, firstEtapeDate) - } - - if (isNullOrUndefined(machineId)) { + if (isNullOrUndefined(d.machineId)) { d.etapes?.forEach(({ typeId }) => { if (!isTDEExist(d.titre!.typeId, d.typeId, typeId)) { console.info(`erreur sur le titre https://camino.beta.gouv.fr/titres/${d.titre!.id}, TDE inconnu ${d.titre!.typeId} ${d.typeId} ${typeId} (${EtapesTypes[typeId].nom})`) diff --git a/packages/api/src/tools/demarches/tests-creation.ts b/packages/api/src/tools/demarches/tests-creation.ts index eee632cb2..6bcdc650f 100644 --- a/packages/api/src/tools/demarches/tests-creation.ts +++ b/packages/api/src/tools/demarches/tests-creation.ts @@ -9,11 +9,12 @@ import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' import { toCommuneId } from 'camino-common/src/static/communes' import { isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, isNullOrUndefined, isNullOrUndefinedOrEmpty } from 'camino-common/src/typescript-tools' import { getDomaineId, getTitreTypeType, TitreTypeId } from 'camino-common/src/static/titresTypes' -import { CaminoMachineId, demarchesDefinitions, machineIdFind } from 'camino-common/src/machines' -import { getMachineFromId } from '../../business/rules-demarches/machines' -import { demarcheEnregistrementDemandeDateFind, DemarcheId, demarcheIdValidator } from 'camino-common/src/demarche' +import { demarchesDefinitions, MachineInfo } from 'camino-common/src/machines' +import { DemarcheId, demarcheIdValidator } from 'camino-common/src/demarche' import { DemarcheStatus, getPhase } from '../../business/rules-demarches/machine-helper' import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' +import { ApiMachineInfo, demarcheEnregistrementDemandeDateFind } from '../../business/rules-demarches/machines' +import { CaminoMachineId } from 'camino-common/src/validators/machine' export type DemarcheWithEtapeForMachinesTest = { id: DemarcheId @@ -48,14 +49,7 @@ const writeEtapesForTest = async () => { const lesDemarchesFiltres = demarches .filter(demarche => isNotNullNorUndefinedNorEmpty(demarche.etapes)) - .filter(demarche => { - const firstEtapeDate = demarcheEnregistrementDemandeDateFind(demarche.etapes) - let machineId: CaminoMachineId | undefined - if (isNotNullNorUndefined(firstEtapeDate)) { - machineId = machineIdFind(demarche.titre!.typeId, demarche.typeId, demarche.id, firstEtapeDate) - } - return machineId === demarcheDefinition.machineId - }) + .filter(demarche => demarche.machineId === demarcheDefinition.machineId) .toSorted((a, b) => a.titreId.localeCompare(b.titreId)) toutesLesEtapes.push( @@ -89,20 +83,25 @@ const writeEtapesForTest = async () => { const firstSaisineDate = etapes.find(etape => etape.etapeTypeId === ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives)?.date ?? etapes[0].date const decalageJour = daysBetween(firstSaisineDate, setDayInMonth(firstSaisineDate, Math.floor(Math.random() * 28))) let statut - const machine = getMachineFromId({ machineId: demarcheDefinition.machineId, titreTypeId: demarche.titre!.typeId, demarcheTypeId: demarche.typeId }) + const machineInfo = MachineInfo.withMachineId(demarche.titre!.typeId, demarche.typeId, demarche.id, demarche.machineId) + if (!machineInfo.valid) { + throw new Error(`La machine associée à la démarche est incohérente : ${machineInfo.error}`) + } + + const machine = new ApiMachineInfo(machineInfo.value) try { - if (isNullOrUndefined(machine)) { + if (isNullOrUndefined(machine.machine)) { console.warn('machine non trouvée') } else { - if (!machine.isEtapesOk(etapes)) { - etapes.splice(0, etapes.length, ...machine.orderMachine(etapes)) - if (!machine.isEtapesOk(etapes)) { + if (!machine.machine.isEtapesOk(etapes)) { + etapes.splice(0, etapes.length, ...machine.machine.orderMachine(etapes)) + if (!machine.machine.isEtapesOk(etapes)) { console.warn(`https://camino.beta.gouv.fr/demarches/${demarche.slug} => démarche N*${index} "${demarcheDefinition.titreTypeIds.join(' ou ')}/${demarche.typeId}"`) - console.warn(machine.interpretMachine(etapes)) + console.warn(machine.machine.interpretMachine(etapes)) return null } } - statut = machine.demarcheStatut(etapes) + statut = machine.machine.demarcheStatut(etapes) const phase = getPhase(statut) if ((phase?.debut ?? null) !== demarche.demarcheDateDebut || (phase?.fin ?? null) !== demarche.demarcheDateFin) { @@ -127,12 +126,12 @@ const writeEtapesForTest = async () => { console.warn('pas de date de début, on ignore') return null } - if (machineIdFind(demarche.titre!.typeId, demarche.typeId, demarche.id, demarcheDebut) !== demarcheDefinition.machineId) { + if (MachineInfo.withDate(demarche.titre!.typeId, demarche.typeId, demarche.id, demarcheDebut).machineId !== demarcheDefinition.machineId) { console.warn('le décalage de jour fait sortir de la machine, on ignore') return null } - return isNullOrUndefined(machine) + return isNullOrUndefined(machine.machine) ? null : { id: demarcheIdValidator.parse(`${index}`), @@ -140,7 +139,7 @@ const writeEtapesForTest = async () => { demarcheTypeId: demarche.typeId, etapes: etapesAnonymes, machineId: demarcheDefinition.machineId, - statut: machine.demarcheStatut(etapesAnonymes), + statut: machine.machine.demarcheStatut(etapesAnonymes), } }) )) diff --git a/packages/api/src/tools/etapes/etapes-complete-check.ts b/packages/api/src/tools/etapes/etapes-complete-check.ts index da9267809..298417dd5 100644 --- a/packages/api/src/tools/etapes/etapes-complete-check.ts +++ b/packages/api/src/tools/etapes/etapes-complete-check.ts @@ -1,7 +1,7 @@ import { titresDemarchesGet } from '../../database/queries/titres-demarches' import { userSuper } from '../../database/user-super' import { isNotNullNorUndefinedNorEmpty, isNullOrUndefined } from 'camino-common/src/typescript-tools' -import { demarcheEnregistrementDemandeDateFind, DemarcheId } from 'camino-common/src/demarche' +import { DemarcheId } from 'camino-common/src/demarche' import { isEtapeComplete } from 'camino-common/src/permissions/titres-etapes' import { iTitreEtapeToFlattenEtape } from '../../api/_format/titres-etapes' import { callAndExit } from '../fp-tools' @@ -13,6 +13,7 @@ import { titreEtapeGet } from '../../database/queries/titres-etapes' import { EtapesTypes } from 'camino-common/src/static/etapesTypes' import { ETAPE_HERITAGE_PROPS } from 'camino-common/src/heritage' import { dateAddMonths, getCurrent, isBefore, setDayInMonth } from 'camino-common/src/date' +import { MachineInfo } from 'camino-common/src/machines' const dateEtapeRecente = setDayInMonth(dateAddMonths(getCurrent(), -8), 1) const etapesValidate = async (pool: Pool, demarcheIds?: DemarcheId[]) => { @@ -35,7 +36,11 @@ const etapesValidate = async (pool: Pool, demarcheIds?: DemarcheId[]) => { if (isNotNullNorUndefinedNorEmpty(demarche.etapes)) { try { const sortedEtapes = demarche.etapes!.toSorted((a, b) => (a.ordre ?? 0) - (b.ordre ?? 0)) - const firstEtapeDate = demarcheEnregistrementDemandeDateFind(demarche.etapes) + const machineInfo = MachineInfo.withMachineId(titreTypeId, demarche.typeId, demarche.id, demarche.machineId) + if (!machineInfo.valid) { + throw new Error(`La machine associée à la démarche est incohérente : ${machineInfo.error}`) + } + for (const etapeSansHeritage of sortedEtapes) { let etape = etapeSansHeritage if (EtapesTypes[etapeSansHeritage.typeId].fondamentale) { @@ -49,7 +54,7 @@ const etapesValidate = async (pool: Pool, demarcheIds?: DemarcheId[]) => { } } if (etape.isBrouillon === ETAPE_IS_NOT_BROUILLON) { - const flattenEtape = await callAndExit(iTitreEtapeToFlattenEtape(etape)) + const flattenEtape = await callAndExit(iTitreEtapeToFlattenEtape(machineInfo.value, etape)) const documents = await callAndExit( getDocumentsByEtapeId( etape.id, @@ -86,19 +91,7 @@ const etapesValidate = async (pool: Pool, demarcheIds?: DemarcheId[]) => { } ) ) - const { valid, errors } = isEtapeComplete( - flattenEtape, - titreTypeId, - demarche.id, - demarche.typeId, - documents, - entrepriseDocuments, - etape.sdomZones, - etape.communes?.map(({ id }) => id) ?? [], - etapeAvis, - userSuper, - firstEtapeDate - ) + const { valid, errors } = isEtapeComplete(flattenEtape, machineInfo.value, documents, entrepriseDocuments, etape.sdomZones, etape.communes?.map(({ id }) => id) ?? [], etapeAvis, userSuper) if (!valid) { const errorMessage = `https://camino.beta.gouv.fr/etapes/${etape.slug} => etape "${etape.typeId}" : ${errors}` diff --git a/packages/api/src/types.ts b/packages/api/src/types.ts index daa204293..41d0de0a4 100644 --- a/packages/api/src/types.ts +++ b/packages/api/src/types.ts @@ -32,6 +32,7 @@ import { KM2 } from 'camino-common/src/number' import { HttpStatus } from 'camino-common/src/http' import { CaminoError } from 'camino-common/src/zod-tools' import { TitreEtapeForMachine } from './business/rules-demarches/machine-common' +import { CaminoMachineId } from 'camino-common/src/validators/machine' export const TitreEtapesTravauxTypes = { AvisDesServicesEtCommissionsConsultatives: 'asc', @@ -216,6 +217,7 @@ export interface ITitreDemarche { demarcheDateFin?: CaminoDate | null publicLecture?: boolean | null entreprisesLecture?: boolean | null + machineId: CaminoMachineId | null etapes?: ITitreEtape[] } diff --git a/packages/api/tests/_utils/administrations-permissions.ts b/packages/api/tests/_utils/administrations-permissions.ts index 2d6264f30..678cccfc8 100644 --- a/packages/api/tests/_utils/administrations-permissions.ts +++ b/packages/api/tests/_utils/administrations-permissions.ts @@ -8,7 +8,7 @@ import options from '../../src/database/queries/_options' import { newDemarcheId, newTitreId, newEtapeId, idGenerate } from '../../src/database/models/_format/id-create' import { TitreTypeId } from 'camino-common/src/static/titresTypes' import { getDocuments } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/documents' -import { EtapeTypeId } from 'camino-common/src/static/etapesTypes' +import { ETAPES_TYPES, EtapeTypeId } from 'camino-common/src/static/etapesTypes' import { firstEtapeDateValidator, toCaminoDate } from 'camino-common/src/date' import { expect } from 'vitest' import { AdministrationId, sortedAdministrations } from 'camino-common/src/static/administrations' @@ -28,6 +28,9 @@ import { exhaustiveCheck, isNotNullNorUndefined, isNullOrUndefined } from 'camin import { HTTP_STATUS } from 'camino-common/src/http' import { insertTitreGraph } from '../integration-test-helper' import { IS_ARM_NON_MECANISE } from 'camino-common/src/static/mecanise' +import { MachineInfo } from 'camino-common/src/machines' +import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes' +import { ETAPES_STATUTS } from 'camino-common/src/static/etapesStatuts' const dir = `${process.cwd()}/files/tmp/` @@ -178,9 +181,13 @@ export const creationCheck = async (pool: Pool, administrationId: string, creer: throw new Error('pour typescript') } - const etapeTypeId = 'mfr' + const etapeTypeId = ETAPES_TYPES.demande - const sections = getSections(titreTypeId, demarche.typeId, etapeTypeId) + const machineInfo = MachineInfo.withMachineId(titreTypeId, demarche.typeId, demarche.id, demarche.machineId) + if (!machineInfo.valid) { + throw new Error(machineInfo.error) + } + const sections = getSections(machineInfo.value, etapeTypeId) const heritageContenu = sections.reduce((acc, section) => { if (!acc[section.id]) { @@ -215,9 +222,9 @@ export const creationCheck = async (pool: Pool, administrationId: string, creer: return acc }, {} as any) - const etapeDate = toCaminoDate('2022-01-01') - const documentTypesIds = getDocuments(titreTypeId, demarche.typeId, etapeTypeId, firstEtapeDateValidator.parse(etapeDate), demarche.id, [], IS_ARM_NON_MECANISE) + + const documentTypesIds = getDocuments(machineInfo.value, etapeTypeId, [], IS_ARM_NON_MECANISE) .filter(({ optionnel }) => !optionnel) .map(({ id }) => id) const etapeDocuments = [] @@ -321,14 +328,15 @@ const titreBuild = ( { id: newDemarcheId(`${titreId}-demarche-id`), titreId, - typeId: 'oct', + typeId: DEMARCHES_TYPES_IDS.Octroi, + machineId: MachineInfo.withDate(titreTypeId, DEMARCHES_TYPES_IDS.Octroi, newDemarcheId(`${titreId}-demarche-id`), firstEtapeDateValidator.parse('2020-01-01')).machineId ?? null, etapes: [ { id: newEtapeId(`${titreId}-demarche-id-etape-id`), - typeId: etapeTypeId || 'mcr', + typeId: etapeTypeId || ETAPES_TYPES.recevabiliteDeLaDemande, ordre: 0, titreDemarcheId: newDemarcheId(`${titreId}-demarche-id`), - statutId: 'enc', + statutId: ETAPES_STATUTS.EN_COURS, isBrouillon: ETAPE_IS_NOT_BROUILLON, date: toCaminoDate('2020-01-01'), administrationsLocales: administrationIdLocale ? [administrationIdLocale] : [], diff --git a/packages/api/tests/_utils/index.ts b/packages/api/tests/_utils/index.ts index 702a8a7f4..2fd0eb996 100644 --- a/packages/api/tests/_utils/index.ts +++ b/packages/api/tests/_utils/index.ts @@ -28,6 +28,11 @@ import { idUserKeycloakRecognised } from '../keycloak' import { isNotNullNorUndefined, isNullOrUndefined } from 'camino-common/src/typescript-tools' import { config } from '../../src/config/index' import { createUtilisateur, getUtilisateurById } from '../../src/database/queries/utilisateurs.queries' +import { MachineInfo } from 'camino-common/src/machines' +import { DemarcheId } from 'camino-common/src/demarche' +import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' +import { TitreTypeId } from 'camino-common/src/static/titresTypes' +import { CaminoMachineId } from 'camino-common/src/validators/machine' export const queryImport = (nom: string): string => fs @@ -132,6 +137,14 @@ const jwtSet = async (pool: Pool, req: request.Test, user: TestUser | undefined) return req } +export const throwableMachineInfoForTestsOnly = (titreTypeId: TitreTypeId, demarcheTypeId: DemarcheTypeId, demarcheId: DemarcheId, machineId: CaminoMachineId | null): MachineInfo => { + const value = MachineInfo.withMachineId(titreTypeId, demarcheTypeId, demarcheId, machineId) + if (!value.valid) { + throw new Error(value.error) + } + return value.value +} + export const userGenerate = async (pool: Pool, user: TestUser): Promise<UserNotNull> => { let idToBuild = 'super' diff --git a/packages/api/vitest.integration.config.ts b/packages/api/vitest.integration.config.ts index 8ddfe9ba1..e661c3e41 100644 --- a/packages/api/vitest.integration.config.ts +++ b/packages/api/vitest.integration.config.ts @@ -20,8 +20,8 @@ export default defineConfig({ name: 'integration', include: ['**/*.test.integration.ts'], setupFiles: path.resolve(__dirname, './tests/vitestSetup.ts'), - testTimeout: 10000, - hookTimeout: 45000, + testTimeout: 20_000, + hookTimeout: 60_000, env: testEnv, pool: 'threads', ...poolOptions, diff --git a/packages/common/src/avisTypes.test.ts b/packages/common/src/avisTypes.test.ts index 66f3d0d0f..dfb6a7b5a 100644 --- a/packages/common/src/avisTypes.test.ts +++ b/packages/common/src/avisTypes.test.ts @@ -7,21 +7,15 @@ import { DEMARCHES_TYPES_IDS } from './static/demarchesTypes' import { ETAPES_TYPES } from './static/etapesTypes' import { IS_ARM_MECANISE } from './static/mecanise' import { TITRES_TYPES_IDS } from './static/titresTypes' +import { MachineInfo } from './machines' describe('getAvisType', () => { const demarcheId = demarcheIdValidator.parse('demarcheId') const firstEtapeDate = firstEtapeDateValidator.parse('2022-01-01') test("les avis obligatoires deviennent optionnels si on n'a pas de machine", () => { - const avis = getAvisTypes( - ETAPES_TYPES.demande, - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, - DEMARCHES_TYPES_IDS.Octroi, - demarcheId, - firstEtapeDateValidator.parse('1980-11-01'), - [], - IS_ARM_MECANISE - ) + const machineInfo = MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('1980-11-01')) + const avis = getAvisTypes(ETAPES_TYPES.demande, machineInfo, [], IS_ARM_MECANISE) expect(avis).toMatchInlineSnapshot(` { "avisDeLaMissionAutoriteEnvironnementale": { @@ -37,23 +31,21 @@ describe('getAvisType', () => { }) test("avis de l'office national des forêts est optionnel pour la procédure spécifique", () => { - const avis = getAvisTypes( - ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, - demarcheId, - firstEtapeDateValidator.parse('2024-11-01'), - [], - IS_ARM_MECANISE - ) + const machineInfo = MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2024-11-01')) + expect(machineInfo.machineId).toBe('ProcedureSpecifique') + const avis = getAvisTypes(ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, machineInfo, [], IS_ARM_MECANISE) expect(avis.avisOfficeNationalDesForets?.optionnel).toBe(true) }) test("avis au cas par cas et avis du propriétaire du sol sont obligatoires pour les demandes d'ARM mécanisée de la procédure spécifique", () => { - expect(getAvisTypes(ETAPES_TYPES.demande, TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate, [], IS_ARM_MECANISE)).toMatchInlineSnapshot( - `{}` - ) + const machineInfo = MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate) + expect(getAvisTypes(ETAPES_TYPES.demande, machineInfo, [], IS_ARM_MECANISE)).toMatchInlineSnapshot(`{}`) expect( - getAvisTypes(ETAPES_TYPES.demande, TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2025-01-01'), [], IS_ARM_MECANISE) + getAvisTypes( + ETAPES_TYPES.demande, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2025-01-01')), + [], + IS_ARM_MECANISE + ) ).toMatchInlineSnapshot(` { "avisCasParCas": { @@ -68,8 +60,8 @@ describe('getAvisType', () => { `) }) test('les avis CGE et AE sont obligatoires pour la machine spécifique', () => { - expect(getAvisTypes(ETAPES_TYPES.saisinesEtAvisCGE_AE, TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate, [], IS_ARM_MECANISE)) - .toMatchInlineSnapshot(` + let machineInfo = MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate) + expect(getAvisTypes(ETAPES_TYPES.saisinesEtAvisCGE_AE, machineInfo, [], IS_ARM_MECANISE)).toMatchInlineSnapshot(` { "autreAvis": { "id": "autreAvis", @@ -85,17 +77,8 @@ describe('getAvisType', () => { }, } `) - expect( - getAvisTypes( - ETAPES_TYPES.saisinesEtAvisCGE_AE, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, - demarcheId, - firstEtapeDateValidator.parse('2025-01-01'), - [], - IS_ARM_MECANISE - ) - ).toMatchInlineSnapshot(` + machineInfo = MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2025-01-01')) + expect(getAvisTypes(ETAPES_TYPES.saisinesEtAvisCGE_AE, machineInfo, [], IS_ARM_MECANISE)).toMatchInlineSnapshot(` { "autreAvis": { "id": "autreAvis", @@ -113,8 +96,8 @@ describe('getAvisType', () => { `) }) test('getAvisType', () => { - expect(getAvisTypes(ETAPES_TYPES.avisDesCollectivites, TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate, [], IS_ARM_MECANISE)) - .toMatchInlineSnapshot(` + let machineInfo = MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate) + expect(getAvisTypes(ETAPES_TYPES.avisDesCollectivites, machineInfo, [], IS_ARM_MECANISE)).toMatchInlineSnapshot(` { "avisDUneCollectivite": { "id": "avisDUneCollectivite", @@ -122,20 +105,8 @@ describe('getAvisType', () => { }, } `) - expect(getAvisTypes(ETAPES_TYPES.demande, TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate, [], IS_ARM_MECANISE)).toMatchInlineSnapshot( - `{}` - ) - expect( - getAvisTypes( - ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, - demarcheId, - firstEtapeDate, - [], - IS_ARM_MECANISE - ) - ).toMatchInlineSnapshot(` + expect(getAvisTypes(ETAPES_TYPES.demande, machineInfo, [], IS_ARM_MECANISE)).toMatchInlineSnapshot(`{}`) + expect(getAvisTypes(ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, machineInfo, [], IS_ARM_MECANISE)).toMatchInlineSnapshot(` { "autreAvis": { "id": "autreAvis", @@ -207,17 +178,7 @@ describe('getAvisType', () => { }, } `) - expect( - getAvisTypes( - ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, - demarcheId, - firstEtapeDate, - [communeIdValidator.parse('97302')], - IS_ARM_MECANISE - ) - ).toMatchInlineSnapshot(` + expect(getAvisTypes(ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, machineInfo, [communeIdValidator.parse('97302')], IS_ARM_MECANISE)).toMatchInlineSnapshot(` { "autreAvis": { "id": "autreAvis", @@ -297,17 +258,8 @@ describe('getAvisType', () => { }, } `) - expect( - getAvisTypes( - ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, - DEMARCHES_TYPES_IDS.Octroi, - demarcheId, - firstEtapeDate, - [communeIdValidator.parse('97302')], - IS_ARM_MECANISE - ) - ).toMatchInlineSnapshot(` + machineInfo = MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate) + expect(getAvisTypes(ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, machineInfo, [communeIdValidator.parse('97302')], IS_ARM_MECANISE)).toMatchInlineSnapshot(` { "autreAvis": { "id": "autreAvis", @@ -391,17 +343,9 @@ describe('getAvisType', () => { }, } `) - expect( - getAvisTypes( - ETAPES_TYPES.consultationDesAdministrationsCentrales, - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_GRANULATS_MARINS, - DEMARCHES_TYPES_IDS.Octroi, - demarcheId, - firstEtapeDate, - [], - IS_ARM_MECANISE - ) - ).toMatchInlineSnapshot(` + machineInfo = MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_GRANULATS_MARINS, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate) + + expect(getAvisTypes(ETAPES_TYPES.consultationDesAdministrationsCentrales, machineInfo, [], IS_ARM_MECANISE)).toMatchInlineSnapshot(` { "autreAvis": { "id": "autreAvis", diff --git a/packages/common/src/avisTypes.ts b/packages/common/src/avisTypes.ts index 6365eff4e..983aeb04e 100644 --- a/packages/common/src/avisTypes.ts +++ b/packages/common/src/avisTypes.ts @@ -1,34 +1,22 @@ -import { FirstEtapeDate } from './date' -import { DemarcheId } from './demarche' -import { isProcedureOuverte, machineIdFind } from './machines' +import { isProcedureOuverte, MachineInfo } from './machines' import { AvisTypeId, AVIS_TYPES, isAvisTypeId } from './static/avisTypes' import { CommuneId } from './static/communes' -import { DemarcheTypeId } from './static/demarchesTypes' import { toDepartementId, DEPARTEMENT_IDS } from './static/departement' import { ETAPES_TYPES, EtapeTypeId } from './static/etapesTypes' import { IsArmMecanise, IS_ARM_NON_MECANISE } from './static/mecanise' -import { TitreTypeId, TITRES_TYPES_IDS, TitresTypes } from './static/titresTypes' +import { TITRES_TYPES_IDS, TitresTypes } from './static/titresTypes' import { TITRES_TYPES_TYPES_IDS } from './static/titresTypesTypes' import { isNotNullNorUndefined } from './typescript-tools' type GetAvisType = Partial<{ [key in AvisTypeId]: { id: key; optionnel: boolean } }> -export const getAvisTypes = ( - etapeTypeId: EtapeTypeId, - titreTypeId: TitreTypeId, - demarcheTypeId: DemarcheTypeId, - demarcheId: DemarcheId, - firstEtapeDate: FirstEtapeDate, - communeIds: CommuneId[], - isArmMecanise: IsArmMecanise -): GetAvisType => { +export const getAvisTypes = (etapeTypeId: EtapeTypeId, machineInfo: MachineInfo, communeIds: CommuneId[], isArmMecanise: IsArmMecanise): GetAvisType => { const avis: GetAvisType = {} - const machineId = machineIdFind(titreTypeId, demarcheTypeId, demarcheId, firstEtapeDate) if (etapeTypeId === ETAPES_TYPES.demande) { - if (titreTypeId === TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX) { + if (machineInfo.titreTypeId === TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX) { avis[AVIS_TYPES.avisProprietaireDuSol] = { id: AVIS_TYPES.avisProprietaireDuSol, optionnel: false } avis[AVIS_TYPES.avisDeLaMissionAutoriteEnvironnementale] = { id: AVIS_TYPES.avisDeLaMissionAutoriteEnvironnementale, optionnel: false } - } else if (titreTypeId === TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX && machineId === 'ProcedureSpecifique') { + } else if (machineInfo.titreTypeId === TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX && machineInfo.machineId === 'ProcedureSpecifique') { avis[AVIS_TYPES.avisCasParCas] = { id: AVIS_TYPES.avisCasParCas, optionnel: isArmMecanise === IS_ARM_NON_MECANISE } avis[AVIS_TYPES.avisProprietaireDuSol] = { id: AVIS_TYPES.avisProprietaireDuSol, optionnel: false } } @@ -52,7 +40,7 @@ export const getAvisTypes = ( avis[AVIS_TYPES.avisCaisseGeneraleSecuriteSociale] = { id: AVIS_TYPES.avisCaisseGeneraleSecuriteSociale, optionnel: true } avis[AVIS_TYPES.autreAvis] = { id: AVIS_TYPES.autreAvis, optionnel: true } // L'avis de l'onf est obligatoire que pour les ARM - avis[AVIS_TYPES.avisOfficeNationalDesForets] = { id: AVIS_TYPES.avisOfficeNationalDesForets, optionnel: machineId === 'ProcedureSpecifique' || titreTypeId !== 'arm' } + avis[AVIS_TYPES.avisOfficeNationalDesForets] = { id: AVIS_TYPES.avisOfficeNationalDesForets, optionnel: machineInfo.machineId === 'ProcedureSpecifique' || machineInfo.titreTypeId !== 'arm' } avis[AVIS_TYPES.expertiseOfficeNationalDesForets] = { id: AVIS_TYPES.expertiseOfficeNationalDesForets, optionnel: true } // TODO 2024-05-14: rendre obligatoire pour les PNMs quand ces derniers seront implémentés avis[AVIS_TYPES.avisParcNaturelMarin] = { id: AVIS_TYPES.avisParcNaturelMarin, optionnel: true } @@ -63,18 +51,18 @@ export const getAvisTypes = ( } // TODO 2024-06-18 Normalement c'est obligatoire si avis propriétaire du sol est favorable avec réserve, optionnel pour le moment - if (TitresTypes[titreTypeId].typeId === TITRES_TYPES_TYPES_IDS.AUTORISATION_D_EXPLOITATION) { + if (TitresTypes[machineInfo.titreTypeId].typeId === TITRES_TYPES_TYPES_IDS.AUTORISATION_D_EXPLOITATION) { avis[AVIS_TYPES.confirmationAccordProprietaireDuSol] = { id: AVIS_TYPES.confirmationAccordProprietaireDuSol, optionnel: true } } } else if (etapeTypeId === ETAPES_TYPES.saisinesEtAvisCGE_AE) { - avis[AVIS_TYPES.avisDuConseilGeneralDeLEconomie] = { id: AVIS_TYPES.avisDuConseilGeneralDeLEconomie, optionnel: machineId !== 'ProcedureSpecifique' } - avis[AVIS_TYPES.avisDeLaMissionAutoriteEnvironnementale] = { id: AVIS_TYPES.avisDeLaMissionAutoriteEnvironnementale, optionnel: machineId !== 'ProcedureSpecifique' } + avis[AVIS_TYPES.avisDuConseilGeneralDeLEconomie] = { id: AVIS_TYPES.avisDuConseilGeneralDeLEconomie, optionnel: machineInfo.machineId !== 'ProcedureSpecifique' } + avis[AVIS_TYPES.avisDeLaMissionAutoriteEnvironnementale] = { id: AVIS_TYPES.avisDeLaMissionAutoriteEnvironnementale, optionnel: machineInfo.machineId !== 'ProcedureSpecifique' } avis[AVIS_TYPES.autreAvis] = { id: AVIS_TYPES.autreAvis, optionnel: true } } else if ([ETAPES_TYPES.consultationDesAdministrationsCentrales, ETAPES_TYPES.expertises].includes(etapeTypeId)) { avis[AVIS_TYPES.autreAvis] = { id: AVIS_TYPES.autreAvis, optionnel: true } } - if (isProcedureOuverte(machineId)) { + if (isProcedureOuverte(machineInfo.machineId)) { for (const avisType in avis) { if (isAvisTypeId(avisType) && isNotNullNorUndefined(avis[avisType])) { avis[avisType].optionnel = true diff --git a/packages/common/src/demarche.test.ts b/packages/common/src/demarche.test.ts index 10280fbdc..112300bd9 100644 --- a/packages/common/src/demarche.test.ts +++ b/packages/common/src/demarche.test.ts @@ -1,9 +1,7 @@ /* eslint-disable no-irregular-whitespace */ -import { test, expect, describe } from 'vitest' -import { canHaveMiseEnConcurrence, demarcheEnregistrementDemandeDateFind, getDemarcheContenu } from './demarche' +import { test, expect } from 'vitest' +import { canHaveMiseEnConcurrence, getDemarcheContenu } from './demarche' import { proprietesGeothermieForagesElementIds } from './static/titresTypes_demarchesTypes_etapesTypes/sections' -import { ETAPES_TYPES } from './static/etapesTypes' -import { toCaminoDate } from './date' import { DEMARCHES_TYPES_IDS } from './static/demarchesTypes' import { TITRES_TYPES_IDS, TitreTypeId } from './static/titresTypes' @@ -473,28 +471,6 @@ test('getDemarcheContenu pxg', () => { `) }) -describe('demarcheDepotDemandeDateFind', () => { - test("pas d'étapes", () => { - expect(demarcheEnregistrementDemandeDateFind([])).toBe(null) - }) - - test('un enregistrement de la demande', () => { - expect( - demarcheEnregistrementDemandeDateFind([ - { typeId: ETAPES_TYPES.demande, date: toCaminoDate('2020-01-01') }, - { typeId: ETAPES_TYPES.enregistrementDeLaDemande, date: toCaminoDate('2024-01-01') }, - ]) - ).toBe(toCaminoDate('2024-01-01')) - }) - test('sans enregistrement de la demande', () => { - expect( - demarcheEnregistrementDemandeDateFind([ - { typeId: ETAPES_TYPES.demande, date: toCaminoDate('2020-01-01') }, - { typeId: ETAPES_TYPES.abrogationDeLaDecision, date: toCaminoDate('2024-01-01') }, - ]) - ).toBe(toCaminoDate('2020-01-01')) - }) -}) test('canHaveMiseEnConcurrence', () => { expect(canHaveMiseEnConcurrence(DEMARCHES_TYPES_IDS.ResiliationAnticipeeDAmodiation, false)).toBe(false) expect(canHaveMiseEnConcurrence(DEMARCHES_TYPES_IDS.ExtensionDePerimetre, false)).toBe(true) diff --git a/packages/common/src/demarche.ts b/packages/common/src/demarche.ts index c41f71590..9bb20b9a0 100644 --- a/packages/common/src/demarche.ts +++ b/packages/common/src/demarche.ts @@ -1,11 +1,11 @@ import { z } from 'zod' import { TITRES_TYPES_IDS, TitreTypeId, getTitreTypeType, titreTypeIdValidator } from './static/titresTypes' -import { CaminoDate, caminoDateValidator, FirstEtapeDate, firstEtapeDateValidator } from './date' +import { caminoDateValidator } from './date' import { communeIdValidator } from './static/communes' import { secteurMaritimeValidator } from './static/facades' import { substanceLegaleIdValidator } from './static/substancesLegales' import { entrepriseIdValidator, etapeEntrepriseDocumentValidator } from './entreprise' -import { ETAPE_TYPE_FOR_CONCURRENCY_DATA, ETAPES_TYPES, EtapeTypeId, etapeTypeIdFondamentaleValidator, etapeTypeIdNonFondamentaleValidator } from './static/etapesTypes' +import { ETAPE_TYPE_FOR_CONCURRENCY_DATA, EtapeTypeId, etapeTypeIdFondamentaleValidator, etapeTypeIdNonFondamentaleValidator } from './static/etapesTypes' import { etapeStatutIdValidator } from './static/etapesStatuts' import { sectionWithValueValidator } from './sections' import { etapeAvisValidator, etapeBrouillonValidator, etapeDocumentValidator, etapeIdValidator, etapeNoteValidator, etapeSlugValidator } from './etape' @@ -18,10 +18,11 @@ import { capitalize } from './strings' import { foretIdValidator } from './static/forets' import { featureCollectionForagesValidator, featureCollectionPointsValidator, featureMultiPolygonValidator } from './perimetre' import { geoSystemeIdValidator } from './static/geoSystemes' -import { isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, isNullOrUndefinedOrEmpty, NonEmptyArray, toSorted } from './typescript-tools' +import { isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty } from './typescript-tools' import { proprietesGeothermieForagesElementIds } from './static/titresTypes_demarchesTypes_etapesTypes/sections' import { titreIdValidator, titreSlugValidator } from './validators/titres' import { DEMARCHES_TYPES_IDS, DemarcheTypeId, demarcheTypeIdValidator } from './static/demarchesTypes' +import { machineIdValidator } from './validators/machine' export const demarcheIdValidator = z.string().brand<'DemarcheId'>() export type DemarcheId = z.infer<typeof demarcheIdValidator> @@ -144,7 +145,7 @@ export const getDemarcheContenu = (etapes: (Pick<DemarcheEtapeCommon, 'sections_ titreTypeId === TITRES_TYPES_IDS.CONCESSION_GRANULATS_MARINS || titreTypeId === TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_GRANULATS_MARINS ) { - // TODO 2023-11-07 à voir avec Pierre-Olivier, les sections VOLUME ne sont jamais utilisées pour les PXW + // TODO 2023-11-07 à voir avec Pierre-Olivier (rip), les sections VOLUME ne sont jamais utilisées pour les PXW const getVolume = (sectionName: 'cxx' | 'pxx'): Record<string, string> => { let volume: number | null = null let volumeUniteId: UniteId | null = null @@ -286,24 +287,6 @@ export const demarcheCreationOutputValidator = z.object({ export type DemarcheCreationOutput = z.infer<typeof demarcheCreationOutputValidator> -type DemarcheEnregistrementDemandeDateFindEtape = { date: CaminoDate; typeId: EtapeTypeId } -export function demarcheEnregistrementDemandeDateFind<T extends DemarcheEnregistrementDemandeDateFindEtape[] | NonEmptyArray<DemarcheEnregistrementDemandeDateFindEtape>>( - titreEtapes: T | undefined -): T extends [DemarcheEnregistrementDemandeDateFindEtape, ...DemarcheEnregistrementDemandeDateFindEtape[]] ? FirstEtapeDate : FirstEtapeDate | null -export function demarcheEnregistrementDemandeDateFind(titreEtapes: DemarcheEnregistrementDemandeDateFindEtape[] | undefined): null | FirstEtapeDate { - if (isNullOrUndefinedOrEmpty(titreEtapes)) { - return null - } - - const titreEtapeDemande = titreEtapes.find(te => te.typeId === ETAPES_TYPES.enregistrementDeLaDemande) - - if (isNotNullNorUndefined(titreEtapeDemande)) { - return firstEtapeDateValidator.parse(titreEtapeDemande.date) - } - - return firstEtapeDateValidator.parse(toSorted(titreEtapes.map(te => te.date))[0]) -} - export const getDemarcheMiseEnConcurrenceValidator = z.object({ demarcheId: demarcheIdValidator, titreNom: z.string(), @@ -323,11 +306,11 @@ export const canHaveMiseEnConcurrence = (demarcheTypeId: DemarcheTypeId, hasTitr export const commonTitreEnConcurrenceValidator = z.object({ demarcheId: demarcheIdValidator, demarcheTypeId: demarcheTypeIdValidator, + machineId: machineIdValidator.nullable(), titreNom: z.string(), titreSlug: titreSlugValidator, titreTypeId: titreTypeIdValidator, titulaireId: entrepriseIdValidator, - firstEtapeDate: firstEtapeDateValidator, }) const commonPerimetreValidator = z.object({ geojson4326_perimetre: featureMultiPolygonValidator, surface: km2Validator }) diff --git a/packages/common/src/machines.test.ts b/packages/common/src/machines.test.ts index b4daa20d7..3cbadf087 100644 --- a/packages/common/src/machines.test.ts +++ b/packages/common/src/machines.test.ts @@ -1,27 +1,125 @@ import { describe, expect, test } from 'vitest' -import { firstEtapeDateValidator } from './date' -import { DATE_DEBUT_PROCEDURE_SPECIFIQUE, isMachineWithConsentement, machineIdFind, isDemarcheIdException } from './machines' +import { dateAddDays, firstEtapeDateValidator } from './date' +import { DATE_DEBUT_PROCEDURE_SPECIFIQUE, isMachineWithConsentement, isDemarcheIdException, MachineInfo, DATE_DEBUT_PROCEDURE_SPECIFIQUE_AXM_ARM } from './machines' import { demarcheIdValidator } from './demarche' +import { DEMARCHES_TYPES_IDS } from './static/demarchesTypes' +import { TITRES_TYPES_IDS } from './static/titresTypes' -describe('machineFind', () => { - test('demarcheDefinitionFind retourne une machine', () => { - expect(machineIdFind('prm', 'oct', demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2023-06-07'))).toStrictEqual('PrmOct') +describe('MachineInfo', () => { + test('MachineInfo.withDate() retourne une machine', () => { + expect( + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2023-06-07')) + .machineId + ).toStrictEqual('AncienLogigrammeOctroiPRM') }) - test('demarcheDefinitionFind ne retourne pas une machine quand la démarche fait partie des exceptions', () => { - expect(machineIdFind('prm', 'oct', demarcheIdValidator.parse('FfJTtP9EEfvf3VZy81hpF7ms'), firstEtapeDateValidator.parse('2023-06-07'))).toBe(undefined) + test('MachineInfo.withDate() ne retourne pas de machine quand la démarche fait partie des exceptions', () => { + expect( + MachineInfo.withDate( + TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, + DEMARCHES_TYPES_IDS.Octroi, + demarcheIdValidator.parse('FfJTtP9EEfvf3VZy81hpF7ms'), + firstEtapeDateValidator.parse('2023-06-07') + ).machineId + ).toBe(undefined) }) - test('demarcheDefinitionFind ne retourne pas une machine quand les étapes sont trop anciennes', () => { - expect(machineIdFind('prm', 'oct', demarcheIdValidator.parse('FfJTtP9EEfvf3VZy81hpF7ms'), firstEtapeDateValidator.parse('2010-06-07'))).toBe(undefined) + test('MachineInfo.withDate() fallback sur une autre machine quand elle est exclue', () => { + expect( + MachineInfo.withDate( + TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + DEMARCHES_TYPES_IDS.Octroi, + demarcheIdValidator.parse('demarcheIdForUnitTests'), + firstEtapeDateValidator.parse(dateAddDays(DATE_DEBUT_PROCEDURE_SPECIFIQUE_AXM_ARM, 20)) + ).machineId + ).toBe('AncienLogigrammeOctroiARM') }) - test('arm pro undef', () => { - expect(machineIdFind('arm', 'pro', demarcheIdValidator.parse('Anything'), firstEtapeDateValidator.parse('2018-10-22'))).toBe(undefined) + test('MachineInfo.withDate() ne retourne pas de machine quand les étapes sont trop anciennes', () => { + expect( + MachineInfo.withDate( + TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, + DEMARCHES_TYPES_IDS.Octroi, + demarcheIdValidator.parse('FfJTtP9EEfvf3VZy81hpF7ms'), + firstEtapeDateValidator.parse('2010-06-07') + ).machineId + ).toBe(undefined) }) - test('demarcheDefinitionFind retourne ProcedureSpecfique dès sa date de début', () => { - expect(machineIdFind('arm', 'oct', demarcheIdValidator.parse('Anything'), firstEtapeDateValidator.parse(DATE_DEBUT_PROCEDURE_SPECIFIQUE))).toBe('ProcedureSpecifique') + test(`MachineInfo.withDate() ne retourne pas de machine pour une prolongation d'Autorisation Recherche Métaux`, () => { + expect( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Prolongation, demarcheIdValidator.parse('Anything'), firstEtapeDateValidator.parse('2018-10-22')) + .machineId + ).toBe(undefined) + }) + + test('MachineInfo.withDate() retourne ProcedureSpecifique dès sa date de début', () => { + const demarcheId = demarcheIdValidator.parse('Anything') + const value = MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse(DATE_DEBUT_PROCEDURE_SPECIFIQUE)) + expect(value.machineId).toBe('ProcedureSpecifique') + expect(value.demarcheId).toBe(demarcheId) + }) + + test('MachineInfo.withMachineId() retourne une machine', () => { + const demarcheId = demarcheIdValidator.parse('Anything') + const machineInfo = MachineInfo.withMachineId(TITRES_TYPES_IDS.CONCESSION_GEOTHERMIE, DEMARCHES_TYPES_IDS.Mutation, demarcheId, 'ProcedureSimplifiee') + expect(machineInfo).toMatchInlineSnapshot(` + { + "valid": true, + "value": MachineInfo { + "_demarcheId": "Anything", + "_demarcheTypeId": "mut", + "_machineId": "ProcedureSimplifiee", + "_titreTypeId": "cxg", + }, + } + `) + }) + + test('MachineInfo.withMachineId() ne retourne pas de machine si le machineId est null', () => { + const machineInfo = MachineInfo.withMachineId(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.AutorisationDOuvertureDeTravaux, demarcheIdValidator.parse('Anything'), null) + expect(machineInfo).toMatchInlineSnapshot(` + { + "valid": true, + "value": MachineInfo { + "_demarcheId": "Anything", + "_demarcheTypeId": "aom", + "_machineId": undefined, + "_titreTypeId": "arm", + }, + } + `) + }) + test("MachineInfo.withMachineId() retourne une erreur en cas d'inconsistence", () => { + expect(MachineInfo.withMachineId(TITRES_TYPES_IDS.CONCESSION_GEOTHERMIE, DEMARCHES_TYPES_IDS.Mutation, demarcheIdValidator.parse('Anything'), null)).toMatchInlineSnapshot( + ` + { + "error": "la machine n'est pas renseignée alors qu'il existe un logigramme potentiel : ProcedureSimplifiee", + "valid": false, + } + ` + ) + + expect(MachineInfo.withMachineId(TITRES_TYPES_IDS.CONCESSION_GEOTHERMIE, DEMARCHES_TYPES_IDS.Mutation, demarcheIdValidator.parse('Anything'), 'AncienLogigrammeOctroiPRM')).toMatchInlineSnapshot(` + { + "error": "INCONSISTENCE, aurait du être ProcedureSimplifiee mais est AncienLogigrammeOctroiPRM", + "valid": false, + } + `) + }) + test('MachineInfo.withMachineId() prend en compte les exceptions', () => { + expect(MachineInfo.withMachineId(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('FfJTtP9EEfvf3VZy81hpF7ms'), null)) + .toMatchInlineSnapshot(` + { + "valid": true, + "value": MachineInfo { + "_demarcheId": "FfJTtP9EEfvf3VZy81hpF7ms", + "_demarcheTypeId": "oct", + "_machineId": undefined, + "_titreTypeId": "prm", + }, + } + `) }) }) describe('isMachineWithConsentement', () => { @@ -29,7 +127,7 @@ describe('isMachineWithConsentement', () => { expect(isMachineWithConsentement('ProcedureSpecifique')).toBe(true) }) test('autre machines', () => { - expect(isMachineWithConsentement('ArmOct')).toBe(false) + expect(isMachineWithConsentement('AncienLogigrammeOctroiARM')).toBe(false) }) }) diff --git a/packages/common/src/machines.ts b/packages/common/src/machines.ts index 3fd7d1f88..f5fd5691c 100644 --- a/packages/common/src/machines.ts +++ b/packages/common/src/machines.ts @@ -2,12 +2,14 @@ import { toCaminoDate, CaminoDate, FirstEtapeDate } from './date' import { DemarcheId, demarcheIdValidator } from './demarche' import { DemarcheTypeId, DEMARCHES_TYPES_IDS, DemarchesTypes } from './static/demarchesTypes' import { TitreTypeId } from './static/titresTypes' -import { NonEmptyArray, isNullOrUndefinedOrEmpty, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, toSorted } from './typescript-tools' +import { NonEmptyArray, isNullOrUndefinedOrEmpty, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, toSorted, isNullOrUndefined } from './typescript-tools' +import { CaminoMachineId } from './validators/machine' // TODO 2025-01-29 attention le jour où on met à jour la date de début de la procédure spécifique // TODO 2025-01-29 pour le consentement, il faudrait que l'on calcule le consentement pour toutes les étapes avec un périmètre, et qu'on aille chercher le consentement lié au titre.props_etape_id export const DATE_DEBUT_PROCEDURE_SPECIFIQUE = toCaminoDate('2400-01-01') export const DATE_DEBUT_PROCEDURE_SPECIFIQUE_AXM_ARM = toCaminoDate('2024-07-01') +export const DATE_DEBUT_PRM_OCT = toCaminoDate('2019-10-31') interface DemarcheDefinition { titreTypeIds: NonEmptyArray<TitreTypeId> @@ -32,27 +34,26 @@ const demarcheTypeIdsCxPr_G: DemarcheTypeId[] = [ DEMARCHES_TYPES_IDS.Retrait, ] const plusVieilleDateEnBase = toCaminoDate('1717-01-09') -const CAMINO_MACHINES = ['ArmOct', 'ArmRenPro', 'PrmOct', 'AxmOct', 'AxmPro', 'ProcedureSimplifiee', 'ProcedureSpecifique'] as const -export type CaminoMachineId = (typeof CAMINO_MACHINES)[number] + export const demarchesDefinitions = [ { titreTypeIds: ['arm'], demarcheTypeIds: ['oct'], dateDebut: toCaminoDate('2019-10-31'), demarcheIdExceptions: [demarcheIdValidator.parse('QauHUIPuv1a5neW3JqVEWh8n'), demarcheIdValidator.parse('XrNwRcLK39y6JZKcsJTV7nju')], - machineId: 'ArmOct', + machineId: 'AncienLogigrammeOctroiARM', }, { titreTypeIds: ['arm'], demarcheTypeIds: [DEMARCHES_TYPES_IDS.RenonciationTotale, DEMARCHES_TYPES_IDS.RenonciationPartielle, DEMARCHES_TYPES_IDS.Prolongation], dateDebut: toCaminoDate('2019-10-31'), demarcheIdExceptions: [], - machineId: 'ArmRenPro', + machineId: 'AncienLogigrammeRenonciationEtProlongationARM', }, { titreTypeIds: ['prm'], demarcheTypeIds: ['oct'], - dateDebut: toCaminoDate('2019-10-31'), + dateDebut: DATE_DEBUT_PRM_OCT, demarcheIdExceptions: [ demarcheIdValidator.parse('FfJTtP9EEfvf3VZy81hpF7ms'), demarcheIdValidator.parse('lynG9hx3x05LaqpySr0qxeca'), @@ -72,7 +73,7 @@ export const demarchesDefinitions = [ demarcheIdValidator.parse('pHJIIJFZpgEccJNt6zTOegzh'), demarcheIdValidator.parse('61af4c6a62b8e477e4b3f43a'), ], - machineId: 'PrmOct', + machineId: 'AncienLogigrammeOctroiPRM', }, { titreTypeIds: ['axm'], @@ -89,7 +90,7 @@ export const demarchesDefinitions = [ demarcheIdValidator.parse('TUI2aBCJRv7Fc1torDlVu8HB'), demarcheIdValidator.parse('FPcbrdR79tjerabHbxtLkMZa'), ], - machineId: 'AxmOct', + machineId: 'AncienLogigrammeOctroiAXM', }, { titreTypeIds: ['axm'], @@ -115,7 +116,7 @@ export const demarchesDefinitions = [ demarcheIdValidator.parse('08eC26bUf4PCr6qj9Rl4Qa1F'), demarcheIdValidator.parse('OBKZ23yRO6e4VP7MyXwgCp6U'), ], - machineId: 'AxmPro', + machineId: 'AncienLogigrammeProlongationAXM', }, { titreTypeIds: ['pxg', 'arg', 'cxr', 'inr', 'prr', 'pxr', 'cxf', 'prf', 'pxf', 'arc', 'apc', 'pcc'], @@ -160,7 +161,7 @@ export const demarchesDefinitions = [ DEMARCHES_TYPES_IDS.Prorogation, ], dateDebut: DATE_DEBUT_PROCEDURE_SPECIFIQUE_AXM_ARM, - demarcheIdExceptions: [], + demarcheIdExceptions: [demarcheIdValidator.parse('demarcheIdForUnitTests')], machineId: 'ProcedureSpecifique', }, ] as const satisfies readonly DemarcheDefinition[] @@ -169,17 +170,88 @@ export const isDemarcheIdException = (id: DemarcheId): boolean => { return demarchesDefinitions.some(definitions => isNotNullNorUndefinedNorEmpty(definitions.demarcheIdExceptions) && definitions.demarcheIdExceptions.includes(id)) } -export const machineIdFind = (titreTypeId: TitreTypeId, demarcheTypeId: DemarcheTypeId, demarcheId: DemarcheId, date: FirstEtapeDate): CaminoMachineId | undefined => { - const definition = toSorted(demarchesDefinitions, (a, b) => b.dateDebut.localeCompare(a.dateDebut)).find( - d => (isNullOrUndefinedOrEmpty(date) || d.dateDebut <= date) && d.titreTypeIds.includes(titreTypeId) && d.demarcheTypeIds.includes(demarcheTypeId) - ) - if (isNotNullNorUndefined(definition) && isNotNullNorUndefinedNorEmpty(definition.demarcheIdExceptions) && definition.demarcheIdExceptions.includes(demarcheId)) { - return undefined +export class MachineInfo { + private _machineId: CaminoMachineId | undefined + private _titreTypeId: TitreTypeId + private _demarcheTypeId: DemarcheTypeId + private _demarcheId: DemarcheId + + private constructor( + titreTypeId: TitreTypeId, + demarcheTypeId: DemarcheTypeId, + demarcheId: DemarcheId, + dateOrMachineId: { type: 'date'; value: FirstEtapeDate } | { type: 'machine'; value: CaminoMachineId | null } + ) { + if (dateOrMachineId.type === 'machine') { + this._machineId = dateOrMachineId.value ?? undefined + } else { + this._machineId = MachineInfo.machineIdFind(titreTypeId, demarcheTypeId, demarcheId, dateOrMachineId.value) + } + + this._titreTypeId = titreTypeId + this._demarcheTypeId = demarcheTypeId + this._demarcheId = demarcheId + } + + static withDate(titreTypeId: TitreTypeId, demarcheTypeId: DemarcheTypeId, demarcheId: DemarcheId, date: FirstEtapeDate): MachineInfo { + return new MachineInfo(titreTypeId, demarcheTypeId, demarcheId, { type: 'date', value: date }) + } + + static withMachineId( + titreTypeId: TitreTypeId, + demarcheTypeId: DemarcheTypeId, + demarcheId: DemarcheId, + machineId: CaminoMachineId | null + ): { valid: true; value: MachineInfo } | { valid: false; error: string } { + const demarcheDefinitionMatching = demarchesDefinitions.filter( + value => + value.titreTypeIds.includes(titreTypeId) && + value.demarcheTypeIds.includes(demarcheTypeId) && + (!isNotNullNorUndefinedNorEmpty(value.demarcheIdExceptions) || !value.demarcheIdExceptions.includes(demarcheId)) + ) + + const logigrammesPotentiels = demarcheDefinitionMatching.map(({ machineId }) => machineId).join(', ') + let found = false + for (const value of demarcheDefinitionMatching) { + if (isNullOrUndefined(machineId) && value.dateDebut === plusVieilleDateEnBase) { + return { valid: false, error: `la machine n'est pas renseignée alors qu'il existe un logigramme potentiel : ${logigrammesPotentiels}` } + } + if (value.machineId === machineId) { + found = true + } + } + if (isNotNullNorUndefined(machineId) && !found) { + return { valid: false, error: `INCONSISTENCE, aurait du être ${logigrammesPotentiels} mais est ${machineId}` } + } + + return { valid: true, value: new MachineInfo(titreTypeId, demarcheTypeId, demarcheId, { type: 'machine', value: machineId }) } } - return definition?.machineId + get machineId(): CaminoMachineId | undefined { + return this._machineId + } + get titreTypeId(): TitreTypeId { + return this._titreTypeId + } + get demarcheTypeId(): DemarcheTypeId { + return this._demarcheTypeId + } + get demarcheId(): DemarcheId { + return this._demarcheId + } + + private static machineIdFind(titreTypeId: TitreTypeId, demarcheTypeId: DemarcheTypeId, demarcheId: DemarcheId, date: FirstEtapeDate | null): CaminoMachineId | undefined { + const definitions = toSorted(demarchesDefinitions, (a, b) => b.dateDebut.localeCompare(a.dateDebut)).filter( + d => (isNullOrUndefinedOrEmpty(date) || d.dateDebut <= date) && d.titreTypeIds.includes(titreTypeId) && d.demarcheTypeIds.includes(demarcheTypeId) + ) + + return definitions.find( + definition => + isNullOrUndefinedOrEmpty(definition.demarcheIdExceptions) || (isNotNullNorUndefinedNorEmpty(definition.demarcheIdExceptions) && !definition.demarcheIdExceptions.includes(demarcheId)) + )?.machineId + } } export const isProcedureOuverte = (machineId: CaminoMachineId | undefined): boolean => machineId === undefined -export const isMachineWithConsentement = (machineId: CaminoMachineId | undefined): boolean => machineId === 'ProcedureSpecifique' +export const isMachineWithConsentement = (machineId: CaminoMachineId | undefined | null): boolean => machineId === 'ProcedureSpecifique' diff --git a/packages/common/src/permissions/etape-form.test.ts b/packages/common/src/permissions/etape-form.test.ts index aa14daaf6..e14ddd39b 100644 --- a/packages/common/src/permissions/etape-form.test.ts +++ b/packages/common/src/permissions/etape-form.test.ts @@ -27,6 +27,7 @@ import { ETAPES_TYPES } from '../static/etapesTypes' import { demarcheIdValidator } from '../demarche' import { DOCUMENTS_TYPES_IDS } from '../static/documentsTypes' import { ETAPES_STATUTS } from '../static/etapesStatuts' +import { MachineInfo } from '../machines' describe('dateTypeStepIsComplete', () => { test.each<User>([ @@ -99,6 +100,8 @@ test('fondamentaleStepIsVisible', () => { expect(fondamentaleStepIsVisible(ETAPES_TYPES.saisinesEtAvisCGE_AE)).toBe(false) }) +const demarcheId = demarcheIdValidator.parse('demarcheId') +const firstEtapeDateFondamentaleStepIsComplete = firstEtapeDateValidator.parse('1000-01-01') test('fondamentaleStepIsComplete', () => { expect( fondamentaleStepIsComplete( @@ -109,8 +112,7 @@ test('fondamentaleStepIsComplete', () => { titulaires: { value: [], heritee: false, etapeHeritee: null }, amodiataires: { value: [], heritee: false, etapeHeritee: null }, }, - DEMARCHES_TYPES_IDS.Amodiation, - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_RADIOACTIF, + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_RADIOACTIF, DEMARCHES_TYPES_IDS.Amodiation, demarcheId, firstEtapeDateFondamentaleStepIsComplete), { ...testBlankUser, role: 'super' } ).valid ).toBe(true) @@ -124,8 +126,7 @@ test('fondamentaleStepIsComplete', () => { titulaires: { value: [], heritee: false, etapeHeritee: null }, amodiataires: { value: [], heritee: false, etapeHeritee: null }, }, - DEMARCHES_TYPES_IDS.Amodiation, - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_RADIOACTIF, + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_RADIOACTIF, DEMARCHES_TYPES_IDS.Amodiation, demarcheId, firstEtapeDateFondamentaleStepIsComplete), { ...testBlankUser, role: 'super' } ) ).toMatchInlineSnapshot(` @@ -147,8 +148,7 @@ test('fondamentaleStepIsComplete', () => { titulaires: { value: [], heritee: false, etapeHeritee: null }, amodiataires: { value: [], heritee: false, etapeHeritee: null }, }, - DEMARCHES_TYPES_IDS.Amodiation, - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_RADIOACTIF, + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_RADIOACTIF, DEMARCHES_TYPES_IDS.Amodiation, demarcheId, firstEtapeDateFondamentaleStepIsComplete), { ...testBlankUser, role: 'super' } ) ).toMatchInlineSnapshot(` @@ -171,8 +171,7 @@ test('fondamentaleStepIsComplete', () => { titulaires: { value: [], heritee: false, etapeHeritee: null }, amodiataires: { value: [], heritee: false, etapeHeritee: null }, }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_RADIOACTIF, + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_RADIOACTIF, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete), { ...testBlankUser, role: 'super' } ) ).toMatchInlineSnapshot(` @@ -193,8 +192,7 @@ test('fondamentaleStepIsComplete', () => { titulaires: { value: [entreprise1Id], heritee: false, etapeHeritee: null }, amodiataires: { value: [], heritee: false, etapeHeritee: null }, }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_RADIOACTIF, + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_RADIOACTIF, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete), { ...testBlankUser, role: 'super' } ) ).toMatchInlineSnapshot(` @@ -214,8 +212,7 @@ test('fondamentaleStepIsComplete', () => { titulaires: { value: [], heritee: false, etapeHeritee: null }, amodiataires: { value: [], heritee: false, etapeHeritee: null }, }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete), { ...testBlankUser, role: 'super' } ) ).toMatchInlineSnapshot(` @@ -235,8 +232,7 @@ test('fondamentaleStepIsComplete', () => { titulaires: { value: [], heritee: false, etapeHeritee: null }, amodiataires: { value: [], heritee: false, etapeHeritee: null }, }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete), { ...testBlankUser, role: 'super' } ) ).toMatchInlineSnapshot(` @@ -257,8 +253,7 @@ test('fondamentaleStepIsComplete', () => { titulaires: { value: [], heritee: false, etapeHeritee: null }, amodiataires: { value: [], heritee: false, etapeHeritee: null }, }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete), { ...testBlankUser, role: 'super' } ) ).toMatchInlineSnapshot(` @@ -280,8 +275,7 @@ test('fondamentaleStepIsComplete', () => { titulaires: { value: [entreprise1Id], heritee: false, etapeHeritee: null }, amodiataires: { value: [], heritee: false, etapeHeritee: null }, }, - DEMARCHES_TYPES_IDS.Mutation, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Mutation, demarcheId, firstEtapeDateFondamentaleStepIsComplete), { ...testBlankUser, role: 'super' } ) ).toMatchInlineSnapshot(` @@ -298,8 +292,7 @@ test('fondamentaleStepIsComplete', () => { titulaires: { value: [], heritee: false, etapeHeritee: null }, amodiataires: { value: [], heritee: false, etapeHeritee: null }, }, - DEMARCHES_TYPES_IDS.Mutation, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Mutation, demarcheId, firstEtapeDateFondamentaleStepIsComplete), { ...testBlankUser, role: 'super' } ) ).toMatchInlineSnapshot(` @@ -320,8 +313,7 @@ test('fondamentaleStepIsComplete', () => { titulaires: { value: [entreprise1Id], heritee: false, etapeHeritee: null }, amodiataires: { value: [], heritee: false, etapeHeritee: null }, }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete), { ...testBlankUser, role: 'entreprise', entrepriseIds: [entreprise1Id] } ) ).toMatchInlineSnapshot(` @@ -338,8 +330,7 @@ test('fondamentaleStepIsComplete', () => { titulaires: { value: [], heritee: false, etapeHeritee: null }, amodiataires: { value: [entreprise1Id], heritee: false, etapeHeritee: null }, }, - DEMARCHES_TYPES_IDS.Amodiation, - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Amodiation, demarcheId, firstEtapeDateFondamentaleStepIsComplete), { ...testBlankUser, role: 'super' } ) ).toMatchInlineSnapshot(` @@ -356,8 +347,7 @@ test('fondamentaleStepIsComplete', () => { titulaires: { value: [], heritee: false, etapeHeritee: null }, amodiataires: { value: [], heritee: false, etapeHeritee: null }, }, - DEMARCHES_TYPES_IDS.Amodiation, - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Amodiation, demarcheId, firstEtapeDateFondamentaleStepIsComplete), { ...testBlankUser, role: 'super' } ) ).toMatchInlineSnapshot(` @@ -371,29 +361,61 @@ test('fondamentaleStepIsComplete', () => { `) }) test('sectionsStepIsVisible', () => { - expect(sectionsStepIsVisible({ typeId: ETAPES_TYPES.demande }, DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX)).toBe(true) expect( - sectionsStepIsVisible({ typeId: ETAPES_TYPES.avisDeLaCommissionDesAutorisationsDeRecherchesMinieres_CARM_ }, DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX) + sectionsStepIsVisible( + { typeId: ETAPES_TYPES.demande }, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete) + ) + ).toBe(true) + expect( + sectionsStepIsVisible( + { typeId: ETAPES_TYPES.avisDeLaCommissionDesAutorisationsDeRecherchesMinieres_CARM_ }, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete) + ) ).toBe(false) }) test('sectionsStepIsComplete', () => { - expect(sectionsStepIsComplete({ typeId: ETAPES_TYPES.demande, contenu: {} }, DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX).valid).toBe(false) + expect( + sectionsStepIsComplete( + { typeId: ETAPES_TYPES.demande, contenu: {} }, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete) + ).valid + ).toBe(false) expect( sectionsStepIsComplete( { typeId: ETAPES_TYPES.demande, contenu: { arm: { mecanise: { value: true, heritee: false, etapeHeritee: null } } } }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete) ).valid ).toBe(true) }) test('perimetreStepIsVisible', () => { - expect(perimetreStepIsVisible({ typeId: ETAPES_TYPES.demande }, DEMARCHES_TYPES_IDS.Octroi)).toBe(true) - expect(perimetreStepIsVisible({ typeId: ETAPES_TYPES.saisinesEtAvisCGE_AE }, DEMARCHES_TYPES_IDS.Octroi)).toBe(false) + expect( + perimetreStepIsVisible( + { typeId: ETAPES_TYPES.demande }, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete) + ) + ).toBe(true) + expect( + perimetreStepIsVisible( + { typeId: ETAPES_TYPES.saisinesEtAvisCGE_AE }, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete) + ) + ).toBe(false) - expect(perimetreStepIsVisible({ typeId: ETAPES_TYPES.demande }, DEMARCHES_TYPES_IDS.Mutation)).toBe(false) - expect(perimetreStepIsVisible({ typeId: ETAPES_TYPES.saisinesEtAvisCGE_AE }, DEMARCHES_TYPES_IDS.Mutation)).toBe(false) + expect( + perimetreStepIsVisible( + { typeId: ETAPES_TYPES.demande }, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Mutation, demarcheId, firstEtapeDateFondamentaleStepIsComplete) + ) + ).toBe(false) + expect( + perimetreStepIsVisible( + { typeId: ETAPES_TYPES.saisinesEtAvisCGE_AE }, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Mutation, demarcheId, firstEtapeDateFondamentaleStepIsComplete) + ) + ).toBe(false) }) test('perimetreStepIsComplete', () => { @@ -416,7 +438,7 @@ test('perimetreStepIsComplete', () => { etapeHeritee: null, }, }, - DEMARCHES_TYPES_IDS.Octroi + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete) ) ).toMatchInlineSnapshot(` { @@ -445,7 +467,7 @@ test('perimetreStepIsComplete', () => { etapeHeritee: null, }, }, - DEMARCHES_TYPES_IDS.Octroi + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete) ).valid ).toBe(true) expect( @@ -467,7 +489,7 @@ test('perimetreStepIsComplete', () => { etapeHeritee: null, }, }, - DEMARCHES_TYPES_IDS.Octroi + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete) ).valid ).toBe(true) expect( @@ -489,7 +511,7 @@ test('perimetreStepIsComplete', () => { etapeHeritee: null, }, }, - DEMARCHES_TYPES_IDS.Octroi + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete) ) ).toMatchInlineSnapshot(` { @@ -518,7 +540,7 @@ test('perimetreStepIsComplete', () => { etapeHeritee: null, }, }, - DEMARCHES_TYPES_IDS.Octroi + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete) ).valid ).toBe(true) }) @@ -563,12 +585,9 @@ test('etapeDocumentsStepIsComplete avec mecanisation', () => { expect( etapeDocumentsStepIsComplete( { typeId: ETAPES_TYPES.demande, contenu: { arm: { mecanise: { value: true, etapeHeritee: null, heritee: false } } }, isBrouillon: ETAPE_IS_NOT_BROUILLON }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - demarcheIdValidator.parse('demarcheId'), + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), [{ etape_document_type_id: DOCUMENTS_TYPES_IDS.decret }], - [], - firstEtapeDateValidator.parse('2022-01-01') + [] ) ).toMatchInlineSnapshot(` { @@ -586,12 +605,9 @@ test('etapeDocumentsStepIsComplete avec mecanisation', () => { expect( etapeDocumentsStepIsComplete( { typeId: ETAPES_TYPES.demande, contenu: { arm: { mecanise: { value: false, etapeHeritee: null, heritee: false } } }, isBrouillon: ETAPE_IS_NOT_BROUILLON }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - demarcheIdValidator.parse('demarcheId'), + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), [{ etape_document_type_id: DOCUMENTS_TYPES_IDS.decret }], - [], - firstEtapeDateValidator.parse('2022-01-01') + [] ) ).toMatchInlineSnapshot(` { @@ -609,12 +625,9 @@ test('etapeDocumentsStepIsComplete', () => { expect( etapeDocumentsStepIsComplete( { typeId: ETAPES_TYPES.consultationDesAdministrationsCentrales, contenu: {}, isBrouillon: ETAPE_IS_NOT_BROUILLON }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - demarcheIdValidator.parse('demarcheId'), + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), [{ etape_document_type_id: DOCUMENTS_TYPES_IDS.decret }], - [], - firstEtapeDateValidator.parse('2022-01-01') + [] ) ).toMatchInlineSnapshot(` { @@ -628,12 +641,9 @@ test('etapeDocumentsStepIsComplete', () => { expect( etapeDocumentsStepIsComplete( { typeId: ETAPES_TYPES.demande, contenu: {}, isBrouillon: ETAPE_IS_BROUILLON }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, - demarcheIdValidator.parse('demarcheId'), + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), axmDocumentsComplete, - [], - firstEtapeDateValidator.parse('2022-01-01') + [] ) ).toMatchInlineSnapshot(` { @@ -644,12 +654,9 @@ test('etapeDocumentsStepIsComplete', () => { expect( etapeDocumentsStepIsComplete( { typeId: ETAPES_TYPES.publicationDansUnJournalLocalOuNational, contenu: {}, isBrouillon: ETAPE_IS_BROUILLON }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, - demarcheIdValidator.parse('demarcheId'), + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), [], - [], - firstEtapeDateValidator.parse('2022-01-01') + [] ) ).toMatchInlineSnapshot(` { @@ -659,13 +666,24 @@ test('etapeDocumentsStepIsComplete', () => { }) test('entrepriseDocumentsStepIsVisible', () => { - expect(entrepriseDocumentsStepIsVisible({ typeId: ETAPES_TYPES.consultationDesAdministrationsCentrales }, DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX)).toBe( - false - ) - expect(entrepriseDocumentsStepIsVisible({ typeId: ETAPES_TYPES.demande }, DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX)).toBe(true) - expect(entrepriseDocumentsStepIsVisible({ typeId: ETAPES_TYPES.publicationDansUnJournalLocalOuNational }, DEMARCHES_TYPES_IDS.Octroi, TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX)).toBe( - false - ) + expect( + entrepriseDocumentsStepIsVisible( + { typeId: ETAPES_TYPES.consultationDesAdministrationsCentrales }, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete) + ) + ).toBe(false) + expect( + entrepriseDocumentsStepIsVisible( + { typeId: ETAPES_TYPES.demande }, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete) + ) + ).toBe(true) + expect( + entrepriseDocumentsStepIsVisible( + { typeId: ETAPES_TYPES.publicationDansUnJournalLocalOuNational }, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete) + ) + ).toBe(false) }) test('entrepriseDocumentsStepIsComplete', () => { expect( @@ -676,16 +694,14 @@ test('entrepriseDocumentsStepIsComplete', () => { amodiataires: { value: [], heritee: false, etapeHeritee: null }, contenu: {}, }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete), [] ).valid ).toBe(true) expect( entrepriseDocumentsStepIsComplete( { typeId: ETAPES_TYPES.demande, titulaires: { value: [], heritee: false, etapeHeritee: null }, amodiataires: { value: [], heritee: false, etapeHeritee: null }, contenu: {} }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete), [] ).valid ).toBe(false) @@ -693,16 +709,14 @@ test('entrepriseDocumentsStepIsComplete', () => { expect( entrepriseDocumentsStepIsComplete( { typeId: ETAPES_TYPES.demande, titulaires: { value: [entreprise1Id], heritee: false, etapeHeritee: null }, amodiataires: { value: [], heritee: false, etapeHeritee: null }, contenu: {} }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete), [] ).valid ).toBe(false) expect( entrepriseDocumentsStepIsComplete( { typeId: ETAPES_TYPES.demande, titulaires: { value: [], heritee: false, etapeHeritee: null }, amodiataires: { value: [entreprise1Id], heritee: false, etapeHeritee: null }, contenu: {} }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete), [] ).valid ).toBe(false) @@ -715,8 +729,7 @@ test('entrepriseDocumentsStepIsComplete', () => { amodiataires: { value: [entreprise1Id], heritee: false, etapeHeritee: null }, contenu: { arm: { mecanise: { value: false, heritee: false, etapeHeritee: null } } }, }, - DEMARCHES_TYPES_IDS.Octroi, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateFondamentaleStepIsComplete), [ { documentTypeId: DOCUMENTS_TYPES_IDS.attestationFiscale, @@ -748,20 +761,20 @@ test('entrepriseDocumentsStepIsComplete', () => { ).toBe(true) }) -const demarcheId = demarcheIdValidator.parse('demarcheId') const firstEtapeDate = firstEtapeDateValidator.parse('2022-01-01') test('etapeAvisStepIsVisible', () => { - expect(etapeAvisStepIsVisible({ typeId: ETAPES_TYPES.demande, contenu: {} }, TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate, [])).toBe( - false - ) + expect( + etapeAvisStepIsVisible( + { typeId: ETAPES_TYPES.demande, contenu: {} }, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), + [] + ) + ).toBe(false) expect( etapeAvisStepIsVisible( { typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, contenu: {} }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, - demarcheId, - firstEtapeDate, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), [] ) ).toBe(true) @@ -772,10 +785,7 @@ test('etapeAvisStepIsComplete', () => { etapeAvisStepIsComplete( { typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, contenu: {} }, [{ avis_type_id: 'autreAvis' }], - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, - demarcheId, - firstEtapeDate, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), [] ).valid ).toBe(false) @@ -783,10 +793,7 @@ test('etapeAvisStepIsComplete', () => { etapeAvisStepIsComplete( { typeId: ETAPES_TYPES.avisDesCollectivites, contenu: {} }, [{ avis_type_id: 'autreAvis' }], - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, - demarcheId, - firstEtapeDate, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), [] ).valid ).toBe(true) diff --git a/packages/common/src/permissions/etape-form.ts b/packages/common/src/permissions/etape-form.ts index fe5cb4238..5e29bfc01 100644 --- a/packages/common/src/permissions/etape-form.ts +++ b/packages/common/src/permissions/etape-form.ts @@ -1,23 +1,20 @@ import { EntrepriseDocumentId, EntrepriseId } from '../entreprise' import { User, isAdministrationAdmin, isAdministrationEditeur, isSuper } from '../roles' import { CommuneId } from '../static/communes' -import { DemarcheTypeId } from '../static/demarchesTypes' import { DocumentsTypes, EntrepriseDocumentTypeId } from '../static/documentsTypes' import { EtapeTypeId, EtapesTypes } from '../static/etapesTypes' import { SDOMZoneId } from '../static/sdom' -import { TitreTypeId } from '../static/titresTypes' import { getDocuments } from '../static/titresTypes_demarchesTypes_etapesTypes/documents' import { getEntrepriseDocuments } from '../static/titresTypes_demarchesTypes_etapesTypes/entrepriseDocuments' import { getSections, getSectionsWithValue } from '../static/titresTypes_demarchesTypes_etapesTypes/sections' import { onlyUnique, NonEmptyArray, isNonEmptyArray, isNullOrUndefinedOrEmpty, isNullOrUndefined, Nullable } from '../typescript-tools' import { sectionsWithValueCompleteValidate } from './sections' import { canEditAmodiataires, canEditDuree, canEditPerimetre, canEditTitulaires } from './titres-etapes' -import { DemarcheId } from '../demarche' -import { FirstEtapeDate } from '../date' import { isArmMecanise } from '../static/mecanise' import { getAvisTypes } from '../avisTypes' import { EtapeDocument, TempEtapeDocument, EtapeAvis, TempEtapeAvis } from '../etape' import { FlattenEtape } from '../etape-form' +import { MachineInfo } from '../machines' type ValidReturn = { valid: true } | { valid: false; errors: NonEmptyArray<string> } @@ -53,12 +50,7 @@ export const fondamentaleStepIsVisible = (etapeTypeId: EtapeTypeId): boolean => return EtapesTypes[etapeTypeId].fondamentale } -export const fondamentaleStepIsComplete = ( - flattened: Pick<FlattenEtape, 'typeId' | 'duree' | 'substances' | 'titulaires' | 'amodiataires'>, - demarcheTypeId: DemarcheTypeId, - titreTypeId: TitreTypeId, - user: User -): ValidReturn => { +export const fondamentaleStepIsComplete = (flattened: Pick<FlattenEtape, 'typeId' | 'duree' | 'substances' | 'titulaires' | 'amodiataires'>, machineInfo: MachineInfo, user: User): ValidReturn => { if (!fondamentaleStepIsVisible(flattened.typeId)) { return { valid: true } } @@ -68,17 +60,17 @@ export const fondamentaleStepIsComplete = ( errors.push('Les substances sont obligatoires') } - const editDuree = canEditDuree(titreTypeId, demarcheTypeId, user) + const editDuree = canEditDuree(machineInfo, user) if (editDuree.visibility === 'present' && editDuree.required && (isNullOrUndefined(flattened.duree.value) || flattened.duree.value === 0)) { errors.push(editDuree.message) } - const editTitulaires = canEditTitulaires(titreTypeId, demarcheTypeId, user) + const editTitulaires = canEditTitulaires(machineInfo, user) if (editTitulaires.visibility === 'present' && editTitulaires.required && isNullOrUndefinedOrEmpty(flattened.titulaires.value)) { errors.push(editTitulaires.message) } - const editAmodiataires = canEditAmodiataires(titreTypeId, demarcheTypeId, user) + const editAmodiataires = canEditAmodiataires(machineInfo, user) if (editAmodiataires.visibility === 'present' && editAmodiataires.required && isNullOrUndefinedOrEmpty(flattened.amodiataires.value)) { errors.push(editAmodiataires.message) } @@ -90,15 +82,15 @@ export const fondamentaleStepIsComplete = ( return { valid: true } } -export const sectionsStepIsVisible = (etape: Pick<FlattenEtape, 'typeId'>, demarcheTypeId: DemarcheTypeId, titreTypeId: TitreTypeId): boolean => { - return getSections(titreTypeId, demarcheTypeId, etape.typeId).length > 0 +export const sectionsStepIsVisible = (etape: Pick<FlattenEtape, 'typeId'>, machineInfo: MachineInfo): boolean => { + return getSections(machineInfo, etape.typeId).length > 0 } -export const sectionsStepIsComplete = (etape: Pick<FlattenEtape, 'typeId' | 'contenu'>, demarcheTypeId: DemarcheTypeId, titreTypeId: TitreTypeId): ValidReturn => { - if (!sectionsStepIsVisible(etape, demarcheTypeId, titreTypeId)) { +export const sectionsStepIsComplete = (etape: Pick<FlattenEtape, 'typeId' | 'contenu'>, machineInfo: MachineInfo): ValidReturn => { + if (!sectionsStepIsVisible(etape, machineInfo)) { return { valid: true } } - const sections = getSections(titreTypeId, demarcheTypeId, etape.typeId) + const sections = getSections(machineInfo, etape.typeId) const sectionsWithValue = getSectionsWithValue(sections, etape.contenu) const errors: string[] = sectionsWithValueCompleteValidate(sectionsWithValue) @@ -109,18 +101,18 @@ export const sectionsStepIsComplete = (etape: Pick<FlattenEtape, 'typeId' | 'con return { valid: true } } -export const perimetreStepIsVisible = (etape: Pick<FlattenEtape, 'typeId'>, demarcheTypeId: DemarcheTypeId): boolean => { - const editPerimetre = canEditPerimetre(demarcheTypeId, etape.typeId) +export const perimetreStepIsVisible = (etape: Pick<FlattenEtape, 'typeId'>, machineInfo: MachineInfo): boolean => { + const editPerimetre = canEditPerimetre(machineInfo, etape.typeId) return editPerimetre.visibility === 'present' } -export const perimetreStepIsComplete = (etape: Pick<FlattenEtape, 'typeId' | 'perimetre'>, demarcheTypeId: DemarcheTypeId): ValidReturn => { - if (!perimetreStepIsVisible(etape, demarcheTypeId)) { +export const perimetreStepIsComplete = (etape: Pick<FlattenEtape, 'typeId' | 'perimetre'>, machineInfo: MachineInfo): ValidReturn => { + if (!perimetreStepIsVisible(etape, machineInfo)) { return { valid: true } } const errors: string[] = [] - const editPerimetre = canEditPerimetre(demarcheTypeId, etape.typeId) + const editPerimetre = canEditPerimetre(machineInfo, etape.typeId) if (editPerimetre.visibility === 'present' && editPerimetre.required && isNullOrUndefined(etape.perimetre.value?.geojson4326Perimetre)) { errors.push(editPerimetre.message) } @@ -138,15 +130,12 @@ export const etapeDocumentsStepIsVisible = (): boolean => { export const etapeDocumentsStepIsComplete = ( etape: Pick<FlattenEtape, 'typeId' | 'contenu' | 'isBrouillon'>, - demarcheTypeId: DemarcheTypeId, - titreTypeId: TitreTypeId, - demarcheId: DemarcheId, + machineInfo: MachineInfo, etapeDocuments: Pick<EtapeDocument | TempEtapeDocument, 'etape_document_type_id'>[], - sdomZoneIds: SDOMZoneId[], - firstEtapeDate: FirstEtapeDate + sdomZoneIds: SDOMZoneId[] ): ValidReturn => { const errors: string[] = [] - const documentTypes = getDocuments(titreTypeId, demarcheTypeId, etape.typeId, firstEtapeDate, demarcheId, sdomZoneIds, isArmMecanise(etape.contenu)) + const documentTypes = getDocuments(machineInfo, etape.typeId, sdomZoneIds, isArmMecanise(etape.contenu)) errors.push( ...documentTypes @@ -161,31 +150,21 @@ export const etapeDocumentsStepIsComplete = ( return { valid: true } } -export const etapeAvisStepIsVisible = ( - etape: Pick<FlattenEtape, 'typeId' | 'contenu'>, - titreTypeId: TitreTypeId, - demarcheTypeId: DemarcheTypeId, - demarcheId: DemarcheId, - firstEtapeDate: FirstEtapeDate, - communeIds: CommuneId[] -): boolean => { - return Object.keys(getAvisTypes(etape.typeId, titreTypeId, demarcheTypeId, demarcheId, firstEtapeDate, communeIds, isArmMecanise(etape.contenu))).length > 0 +export const etapeAvisStepIsVisible = (etape: Pick<FlattenEtape, 'typeId' | 'contenu'>, machineInfo: MachineInfo, communeIds: CommuneId[]): boolean => { + return Object.keys(getAvisTypes(etape.typeId, machineInfo, communeIds, isArmMecanise(etape.contenu))).length > 0 } export const etapeAvisStepIsComplete = ( etape: Pick<FlattenEtape, 'typeId' | 'contenu'>, etapeAvis: Pick<EtapeAvis | TempEtapeAvis, 'avis_type_id'>[], - titreTypeId: TitreTypeId, - demarcheTypeId: DemarcheTypeId, - demarcheId: DemarcheId, - firstEtapeDate: FirstEtapeDate, + machineInfo: MachineInfo, communeIds: CommuneId[] ): ValidReturn => { - if (!etapeAvisStepIsVisible(etape, titreTypeId, demarcheTypeId, demarcheId, firstEtapeDate, communeIds)) { + if (!etapeAvisStepIsVisible(etape, machineInfo, communeIds)) { return { valid: true } } - const avisTypes = getAvisTypes(etape.typeId, titreTypeId, demarcheTypeId, demarcheId, firstEtapeDate, communeIds, isArmMecanise(etape.contenu)) + const avisTypes = getAvisTypes(etape.typeId, machineInfo, communeIds, isArmMecanise(etape.contenu)) if (Object.values(avisTypes).some(avisType => !avisType.optionnel && etapeAvis.every(avis => avis.avis_type_id !== avisType.id))) { return { valid: false, errors: ['Il manque des avis obligatoires'] } } @@ -193,24 +172,23 @@ export const etapeAvisStepIsComplete = ( return { valid: true } } -export const entrepriseDocumentsStepIsVisible = (etape: Pick<FlattenEtape, 'typeId'>, demarcheTypeId: DemarcheTypeId, titreTypeId: TitreTypeId): boolean => { - return getEntrepriseDocuments(titreTypeId, demarcheTypeId, etape.typeId).length > 0 +export const entrepriseDocumentsStepIsVisible = (etape: Pick<FlattenEtape, 'typeId'>, machineInfo: MachineInfo): boolean => { + return getEntrepriseDocuments(machineInfo, etape.typeId).length > 0 } export const entrepriseDocumentsStepIsComplete = ( etape: Pick<FlattenEtape, 'typeId' | 'contenu' | 'titulaires' | 'amodiataires'>, - demarcheTypeId: DemarcheTypeId, - titreTypeId: TitreTypeId, + machineInfo: MachineInfo, entreprisesDocuments: Pick<SelectedEntrepriseDocument, 'documentTypeId' | 'entrepriseId'>[] ): ValidReturn => { - if (!entrepriseDocumentsStepIsVisible(etape, demarcheTypeId, titreTypeId)) { + if (!entrepriseDocumentsStepIsVisible(etape, machineInfo)) { return { valid: true } } - const documentTypes = getEntrepriseDocuments(titreTypeId, demarcheTypeId, etape.typeId) + const documentTypes = getEntrepriseDocuments(machineInfo, etape.typeId) const entrepriseIds = [...etape.titulaires.value, ...etape.amodiataires.value].filter(onlyUnique) - if (isNullOrUndefinedOrEmpty(entrepriseIds) && getEntrepriseDocuments(titreTypeId, demarcheTypeId, etape.typeId).some(({ optionnel }) => !optionnel)) { + if (isNullOrUndefinedOrEmpty(entrepriseIds) && getEntrepriseDocuments(machineInfo, etape.typeId).some(({ optionnel }) => !optionnel)) { return { valid: false, errors: ["Il y a des documents d'entreprise obligatoires, mais il n'y a pas de titulaire"] } } diff --git a/packages/common/src/permissions/titres-demarches.test.ts b/packages/common/src/permissions/titres-demarches.test.ts index 38749f47d..ac5d29d9d 100644 --- a/packages/common/src/permissions/titres-demarches.test.ts +++ b/packages/common/src/permissions/titres-demarches.test.ts @@ -3,11 +3,13 @@ import { AdministrationId } from '../static/administrations' import { canEditDemarche, canCreateTravaux, canDeleteDemarche, canCreateDemarche, canPublishResultatMiseEnConcurrence, canCreateEtapeByDemarche } from './titres-demarches' import { testBlankUser, TestUser } from '../tests-utils' import { TitresStatutIds } from '../static/titresStatuts' -import { caminoDateValidator, dateAddDays, toCaminoDate } from '../date' +import { caminoDateValidator, dateAddDays, firstEtapeDateValidator } from '../date' import { demarcheIdValidator } from '../demarche' import { ETAPES_TYPES } from '../static/etapesTypes' import { EtapesTypesEtapesStatuts } from '../static/etapesTypesEtapesStatuts' -import { DATE_DEBUT_PROCEDURE_SPECIFIQUE } from '../machines' +import { DATE_DEBUT_PROCEDURE_SPECIFIQUE, MachineInfo } from '../machines' +import { TITRES_TYPES_IDS } from '../static/titresTypes' +import { DEMARCHES_TYPES_IDS } from '../static/demarchesTypes' describe('canEditDemarche', () => { test.each<[AdministrationId, boolean]>([ @@ -116,24 +118,32 @@ describe('canCreateTravaux', () => { describe('canPublishResultatMiseEnConcurrence', () => { const demarcheId = demarcheIdValidator.parse('demarcheId') test('machine non procédure spécifique', () => { - expect(canPublishResultatMiseEnConcurrence({ ...testBlankUser, role: 'super' }, 'arm', 'oct', [{ date: toCaminoDate('2020-01-01'), etape_statut_id: 'fai', etape_type_id: 'mfr' }], demarcheId)) - .toMatchInlineSnapshot(` - { - "errors": [ - "Cette démarche n'est pas une procédure spécifique", - ], - "valid": false, - } - `) + expect( + canPublishResultatMiseEnConcurrence( + { ...testBlankUser, role: 'super' }, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse('2020-01-01')), + [{ etape_statut_id: 'fai', etape_type_id: 'mfr' }] + ) + ).toMatchInlineSnapshot(` + { + "errors": [ + "Cette démarche n'est pas une procédure spécifique", + ], + "valid": false, + } + `) }) test('mise en concurrence non terminée', () => { expect( canPublishResultatMiseEnConcurrence( { ...testBlankUser, role: 'super' }, - 'arm', - 'oct', - [{ date: dateAddDays(DATE_DEBUT_PROCEDURE_SPECIFIQUE, 12), etape_statut_id: 'fai', etape_type_id: 'mfr' }], - demarcheId + MachineInfo.withDate( + TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + DEMARCHES_TYPES_IDS.Octroi, + demarcheId, + firstEtapeDateValidator.parse(dateAddDays(DATE_DEBUT_PROCEDURE_SPECIFIQUE, 12)) + ), + [{ etape_statut_id: 'fai', etape_type_id: 'mfr' }] ) ).toMatchInlineSnapshot(` { @@ -148,17 +158,18 @@ describe('canPublishResultatMiseEnConcurrence', () => { expect( canPublishResultatMiseEnConcurrence( { ...testBlankUser, role: 'defaut' }, - 'arm', - 'oct', + MachineInfo.withDate( + TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + DEMARCHES_TYPES_IDS.Octroi, + demarcheId, + firstEtapeDateValidator.parse(dateAddDays(DATE_DEBUT_PROCEDURE_SPECIFIQUE, 10)) + ), [ { etape_type_id: ETAPES_TYPES.avisDeMiseEnConcurrenceAuJORF, etape_statut_id: EtapesTypesEtapesStatuts.avisDeMiseEnConcurrenceAuJORF.TERMINE.etapeStatutId, - demarche_id_en_concurrence: null, - date: dateAddDays(DATE_DEBUT_PROCEDURE_SPECIFIQUE, 10), }, - ], - demarcheId + ] ) ).toMatchInlineSnapshot(` { @@ -171,7 +182,18 @@ describe('canPublishResultatMiseEnConcurrence', () => { }) test("pas d'étapes", () => { - expect(canPublishResultatMiseEnConcurrence({ ...testBlankUser, role: 'super' }, 'arm', 'oct', [], demarcheId)).toMatchInlineSnapshot(` + expect( + canPublishResultatMiseEnConcurrence( + { ...testBlankUser, role: 'super' }, + MachineInfo.withDate( + TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + DEMARCHES_TYPES_IDS.Octroi, + demarcheId, + firstEtapeDateValidator.parse(dateAddDays(DATE_DEBUT_PROCEDURE_SPECIFIQUE, 10)) + ), + [] + ) + ).toMatchInlineSnapshot(` { "errors": [ "Au moins une étape est nécessaire", @@ -185,17 +207,18 @@ describe('canPublishResultatMiseEnConcurrence', () => { expect( canPublishResultatMiseEnConcurrence( { ...testBlankUser, role: 'admin', administrationId: 'aut-mrae-guyane-01' }, - 'arm', - 'oct', + MachineInfo.withDate( + TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + DEMARCHES_TYPES_IDS.Octroi, + demarcheId, + firstEtapeDateValidator.parse(dateAddDays(DATE_DEBUT_PROCEDURE_SPECIFIQUE, 10)) + ), [ { etape_type_id: ETAPES_TYPES.avisDeMiseEnConcurrenceAuJORF, etape_statut_id: EtapesTypesEtapesStatuts.avisDeMiseEnConcurrenceAuJORF.TERMINE.etapeStatutId, - demarche_id_en_concurrence: null, - date: dateAddDays(DATE_DEBUT_PROCEDURE_SPECIFIQUE, 10), }, - ], - demarcheId + ] ) ).toMatchInlineSnapshot(` { @@ -209,23 +232,22 @@ describe('canPublishResultatMiseEnConcurrence', () => { expect( canPublishResultatMiseEnConcurrence( { ...testBlankUser, role: 'editeur', administrationId: 'aut-mrae-guyane-01' }, - 'arm', - 'oct', + MachineInfo.withDate( + TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + DEMARCHES_TYPES_IDS.Octroi, + demarcheId, + firstEtapeDateValidator.parse(dateAddDays(DATE_DEBUT_PROCEDURE_SPECIFIQUE, 10)) + ), [ { etape_type_id: ETAPES_TYPES.avisDeMiseEnConcurrenceAuJORF, etape_statut_id: EtapesTypesEtapesStatuts.avisDeMiseEnConcurrenceAuJORF.TERMINE.etapeStatutId, - demarche_id_en_concurrence: null, - date: dateAddDays(DATE_DEBUT_PROCEDURE_SPECIFIQUE, 10), }, { etape_type_id: ETAPES_TYPES.resultatMiseEnConcurrence, etape_statut_id: EtapesTypesEtapesStatuts.resultatMiseEnConcurrence.ACCEPTE.etapeStatutId, - demarche_id_en_concurrence: null, - date: dateAddDays(DATE_DEBUT_PROCEDURE_SPECIFIQUE, 11), }, - ], - demarcheId + ] ) ).toMatchInlineSnapshot(` { diff --git a/packages/common/src/permissions/titres-demarches.ts b/packages/common/src/permissions/titres-demarches.ts index 9e1c33234..4e2703a52 100644 --- a/packages/common/src/permissions/titres-demarches.ts +++ b/packages/common/src/permissions/titres-demarches.ts @@ -10,10 +10,10 @@ import { canCreateEtape } from './titres-etapes' import { TitreGetDemarche } from '../titres' import { CaminoValid, isNotNullNorUndefinedNorEmpty, isNullOrUndefined } from '../typescript-tools' import { ETAPE_IS_BROUILLON } from '../etape' -import { demarcheEnregistrementDemandeDateFind, DemarcheEtape, DemarcheId } from '../demarche' -import { machineIdFind } from '../machines' +import { DemarcheEtape } from '../demarche' import { ETAPES_TYPES, EtapesTypes } from '../static/etapesTypes' import { EtapesTypesEtapesStatuts } from '../static/etapesTypesEtapesStatuts' +import { MachineInfo } from '../machines' const hasOneDemarcheWithoutPhase = (demarches: Pick<TitreGetDemarche, 'demarche_date_debut'>[]): boolean => { // Si il y a une seule démarche et qu'elle n'a pas encore créée de phase, alors on ne peut pas créer une deuxième démarche @@ -90,22 +90,19 @@ export const canCreateEtapeByDemarche = ( export const canPublishResultatMiseEnConcurrence = ( user: User, - titre_type_id: TitreTypeId, - demarche_type_id: DemarcheTypeId, - etapes: Pick<DemarcheEtape, 'etape_type_id' | 'demarche_id_en_concurrence' | 'date' | 'etape_statut_id'>[], - id: DemarcheId + + machineInfo: MachineInfo, + etapes: Pick<DemarcheEtape, 'etape_type_id' | 'etape_statut_id'>[] ): CaminoValid<string> => { if (!isSuper(user) && !isAdministrationAdmin(user) && !isAdministrationEditeur(user)) { return { valid: false, errors: ["L'utilisateur ne dispose pas des droits suffisants"] } } - const firstEtapeDate = demarcheEnregistrementDemandeDateFind(etapes.map(etape => ({ ...etape, typeId: etape.etape_type_id }))) - if (isNullOrUndefined(firstEtapeDate)) { + if (etapes.length === 0) { return { valid: false, errors: ['Au moins une étape est nécessaire'] } } - const machineId = machineIdFind(titre_type_id, demarche_type_id, id, firstEtapeDate) - if (machineId !== 'ProcedureSpecifique') { + if (machineInfo.machineId !== 'ProcedureSpecifique') { return { valid: false, errors: ["Cette démarche n'est pas une procédure spécifique"] } } diff --git a/packages/common/src/permissions/titres-etapes.test.ts b/packages/common/src/permissions/titres-etapes.test.ts index 80ec0cb38..070cd7223 100644 --- a/packages/common/src/permissions/titres-etapes.test.ts +++ b/packages/common/src/permissions/titres-etapes.test.ts @@ -38,7 +38,7 @@ import { SDOMZoneIds } from '../static/sdom' import { PartialRecord } from '../typescript-tools' import { Hectare, hectareToKm2, hectareValidator, KM2, km2toHectare, km2Validator } from '../number' import { demarcheIdValidator } from '../demarche' -import { DATE_DEBUT_PROCEDURE_SPECIFIQUE, DATE_DEBUT_PROCEDURE_SPECIFIQUE_AXM_ARM } from '../machines' +import { DATE_DEBUT_PROCEDURE_SPECIFIQUE, DATE_DEBUT_PROCEDURE_SPECIFIQUE_AXM_ARM, MachineInfo } from '../machines' console.warn = vi.fn() @@ -52,18 +52,34 @@ test.each<{ titreTypeId: TitreTypeId; demarcheTypeId: DemarcheTypeId; canEdit: b { titreTypeId: 'prm', demarcheTypeId: 'exp', canEdit: false }, { titreTypeId: 'prm', demarcheTypeId: 'mut', canEdit: false }, ])('canEditDuree $titreTypeId | $demarcheTypeId | $canEdit', ({ titreTypeId, demarcheTypeId, canEdit }) => - expect(canEditDuree(titreTypeId, demarcheTypeId, { ...testBlankUser, role: 'entreprise', entrepriseIds: [newEntrepriseId('entrepriseId')] }).visibility === 'present').toEqual(canEdit) + expect( + canEditDuree(MachineInfo.withDate(titreTypeId, demarcheTypeId, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01')), { + ...testBlankUser, + role: 'entreprise', + entrepriseIds: [newEntrepriseId('entrepriseId')], + }).visibility === 'present' + ).toEqual(canEdit) ) test('un super ou une admininstration peut éditer la durée d un octroi d ARM', () => { - expect(canEditDuree('arm', 'oct', { ...testBlankUser, role: 'super' })).toMatchInlineSnapshot(` + expect( + canEditDuree( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01')), + { ...testBlankUser, role: 'super' } + ) + ).toMatchInlineSnapshot(` { "message": "la durée est obligatoire pour une démarche octroi", "required": true, "visibility": "present", } `) - expect(canEditDuree('arm', 'oct', { ...testBlankUser, role: 'admin', administrationId: 'dea-guyane-01' })).toMatchInlineSnapshot(` + expect( + canEditDuree( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01')), + { ...testBlankUser, role: 'admin', administrationId: 'dea-guyane-01' } + ) + ).toMatchInlineSnapshot(` { "message": "la durée est obligatoire pour une démarche octroi", "required": true, @@ -89,7 +105,10 @@ test.each<{ titreTypeId: TitreTypeId; demarcheTypeId: DemarcheTypeId; etapeTypeI { titreTypeId: 'prm', etapeTypeId: 'mfr', demarcheTypeId: 'mut', user: { role: 'super' }, canEdit: false }, { titreTypeId: 'prm', etapeTypeId: 'dpu', demarcheTypeId: 'dec', user: { role: 'defaut' }, canEdit: false }, ])('canEditDate $titreTypeId | $demarcheTypeId | $etapeTypeId | $user | $canEdit', ({ titreTypeId, demarcheTypeId, etapeTypeId, user, canEdit }) => { - expect(canEditDates(titreTypeId, demarcheTypeId, etapeTypeId, { ...user, ...testBlankUser }).visibility === 'present').toEqual(canEdit) + expect( + canEditDates(MachineInfo.withDate(titreTypeId, demarcheTypeId, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01')), etapeTypeId, { ...user, ...testBlankUser }) + .visibility === 'present' + ).toEqual(canEdit) }) test.each<{ titreTypeId: TitreTypeId; user: TestUser; canEdit: boolean }>([ @@ -101,13 +120,19 @@ test.each<{ titreTypeId: TitreTypeId; user: TestUser; canEdit: boolean }>([ { titreTypeId: 'prm', user: { role: 'lecteur', administrationId: ADMINISTRATION_IDS.BRGM }, canEdit: false }, { titreTypeId: 'prm', user: { role: 'defaut' }, canEdit: false }, ])('canEditAmodiataires $titreTypeId | $user | $canEdit', ({ titreTypeId, user, canEdit }) => { - const editAmodiataires = canEditAmodiataires(titreTypeId, DEMARCHES_TYPES_IDS.Octroi, { ...user, ...testBlankUser }) + const editAmodiataires = canEditAmodiataires(MachineInfo.withDate(titreTypeId, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01')), { + ...user, + ...testBlankUser, + }) expect(editAmodiataires.visibility === 'present').toEqual(canEdit) }) test('canEditAmodiataires by demarcheTypeId', () => { const result = Object.entries(DEMARCHES_TYPES_IDS).reduce<PartialRecord<string, InputPresence>>((acc, [key, value]) => { - acc[key] = canEditAmodiataires(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, value, { ...testBlankUser, role: 'super' }) + acc[key] = canEditAmodiataires(MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, value, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01')), { + ...testBlankUser, + role: 'super', + }) return acc }, {}) @@ -132,13 +157,19 @@ test.each<{ titreTypeId: TitreTypeId; user: TestUser; canEdit: boolean }>([ { titreTypeId: 'arm', user: { role: 'lecteur', administrationId: ADMINISTRATION_IDS.BRGM }, canEdit: false }, { titreTypeId: 'arm', user: { role: 'defaut' }, canEdit: false }, ])('canEditTitulaires $titreTypeId | $user | $canEdit', ({ titreTypeId, user, canEdit }) => { - const editTitulaires = canEditTitulaires(titreTypeId, DEMARCHES_TYPES_IDS.Octroi, { ...user, ...testBlankUser }) + const editTitulaires = canEditTitulaires(MachineInfo.withDate(titreTypeId, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01')), { + ...user, + ...testBlankUser, + }) expect(editTitulaires.visibility === 'present').toEqual(canEdit) }) test('canEditTitulaires by demarcheTypeId', () => { const result = Object.entries(DEMARCHES_TYPES_IDS).reduce<PartialRecord<string, ReturnType<typeof canEditTitulaires>>>((acc, [key, value]) => { - acc[key] = canEditTitulaires(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, value, { ...testBlankUser, role: 'super' }) + acc[key] = canEditTitulaires(MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, value, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01')), { + ...testBlankUser, + role: 'super', + }) return acc }, {}) @@ -148,7 +179,10 @@ test('canEditTitulaires by demarcheTypeId', () => { test('canEditPerimetre by demarcheTypeId', () => { const result = Object.entries(DEMARCHES_TYPES_IDS).reduce<PartialRecord<string, ReturnType<typeof canEditPerimetre>>>((acc, [key, value]) => { - acc[key] = canEditPerimetre(value, ETAPES_TYPES.demande) + acc[key] = canEditPerimetre( + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, value, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01')), + ETAPES_TYPES.demande + ) return acc }, {}) @@ -157,14 +191,24 @@ test('canEditPerimetre by demarcheTypeId', () => { }) test('canEditPerimetre fondamentale', () => { - expect(canEditPerimetre(DEMARCHES_TYPES_IDS.Octroi, ETAPES_TYPES.demande)).toMatchInlineSnapshot(` + expect( + canEditPerimetre( + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01')), + ETAPES_TYPES.demande + ) + ).toMatchInlineSnapshot(` { "message": "le périmètre est obligatoire pour une démarche octroi", "required": true, "visibility": "present", } `) - expect(canEditPerimetre(DEMARCHES_TYPES_IDS.Octroi, ETAPES_TYPES.avisDeDemandeConcurrente)).toMatchInlineSnapshot(` + expect( + canEditPerimetre( + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01')), + ETAPES_TYPES.avisDeDemandeConcurrente + ) + ).toMatchInlineSnapshot(` { "message": "une étape avis de demande concurrente ne peut pas inclure de périmètre", "visibility": "absent", @@ -419,9 +463,7 @@ test("teste la complétude d'une demande d'AXM faite par un utilisateur entrepri expect( isEtapeComplete( { ...etapeComplete, isBrouillon: ETAPE_IS_BROUILLON }, - 'axm', - demarcheIdValidator.parse('demarcheId'), - 'oct', + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), axmDocuments, axmEntrepriseDocuments, [SDOMZoneIds.Zone1], @@ -431,8 +473,7 @@ test("teste la complétude d'une demande d'AXM faite par un utilisateur entrepri ...testBlankUser, role: 'entreprise', entrepriseIds: [entrepriseIdValidator.parse('id1')], - }, - firstEtapeDateValidator.parse('2022-01-01') + } ) ).toMatchInlineSnapshot(` { @@ -448,9 +489,7 @@ test("teste la complétude d'une demande d'AXM faite par un utilisateur entrepri expect( isEtapeComplete( { ...etapeComplete, isBrouillon: ETAPE_IS_BROUILLON }, - 'axm', - demarcheIdValidator.parse('demarcheId'), - 'oct', + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), axmDocuments, axmEntrepriseDocuments, [], @@ -460,8 +499,7 @@ test("teste la complétude d'une demande d'AXM faite par un utilisateur entrepri ...testBlankUser, role: 'entreprise', entrepriseIds: [entrepriseIdValidator.parse('id1')], - }, - firstEtapeDateValidator.parse('2022-01-01') + } ) ).toStrictEqual({ valid: true, errors: null }) }) @@ -470,9 +508,7 @@ test("teste la complétude d'une demande d'ARM", () => { expect( isEtapeComplete( { ...etapeComplete, contenu: { arm: { mecanise: { value: false, etapeHeritee: null, heritee: false } } } }, - 'arm', - demarcheIdValidator.parse('demarcheId'), - 'oct', + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), armDocuments, armEntrepriseDocuments, [], @@ -481,8 +517,7 @@ test("teste la complétude d'une demande d'ARM", () => { { ...testBlankUser, role: 'super', - }, - firstEtapeDateValidator.parse('2022-01-01') + } ) ).toStrictEqual({ valid: true, errors: null }) }) @@ -501,16 +536,13 @@ test.each<[SubstanceLegaleId[], EtapeTypeId, TitreTypeId, IsEtapeCompleteDocumen const result = isEtapeComplete( titreEtape, - titreType, - demarcheIdValidator.parse('demarcheId'), - 'oct', + MachineInfo.withDate(titreType, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), testDocuments, entrepriseDocuments, [], [], axmDemandeAvis, - { ...testBlankUser, role: 'super' }, - firstEtapeDateValidator.parse('2022-01-01') + { ...testBlankUser, role: 'super' } ) expect(result.valid, JSON.stringify(result)).toBe(true) @@ -530,16 +562,13 @@ test.each<[SubstanceLegaleId[], EtapeTypeId, TitreTypeId, IsEtapeCompleteDocumen const result = isEtapeComplete( titreEtape, - titreType, - demarcheIdValidator.parse('demarcheId'), - 'oct', + MachineInfo.withDate(titreType, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), testDocuments, entrepriseDocuments, [], [], [], - { ...testBlankUser, role: 'super' }, - firstEtapeDateValidator.parse('2022-01-01') + { ...testBlankUser, role: 'super' } ) const errorLabel = 'Les substances sont obligatoires' @@ -577,16 +606,13 @@ test.each<[FeatureMultiPolygon | null, EtapeTypeId, TitreTypeId, IsEtapeComplete const result = isEtapeComplete( titreEtape, - titreType, - demarcheIdValidator.parse('demarcheId'), - 'oct', + MachineInfo.withDate(titreType, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), documents, entrepriseDocuments, [], [], [], - { ...testBlankUser, role: 'super' }, - firstEtapeDateValidator.parse('2022-01-01') + { ...testBlankUser, role: 'super' } ) const errorLabel = 'le périmètre est obligatoire pour une démarche octroi' @@ -624,16 +650,13 @@ test.each<[FeatureMultiPolygon | null, EtapeTypeId, TitreTypeId, IsEtapeComplete const result = isEtapeComplete( titreEtape, - titreType, - demarcheIdValidator.parse('demarcheId'), - 'oct', + MachineInfo.withDate(titreType, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), documents, entrepriseDocuments, [], [], axmDemandeAvis, - { ...testBlankUser, role: 'super' }, - firstEtapeDateValidator.parse('2022-01-01') + { ...testBlankUser, role: 'super' } ) expect(result).toStrictEqual({ valid: true, errors: null }) @@ -642,16 +665,13 @@ test.each<[FeatureMultiPolygon | null, EtapeTypeId, TitreTypeId, IsEtapeComplete test("une demande d'ARM mécanisée a des documents obligatoires supplémentaires", () => { const errors = isEtapeComplete( { ...etapeComplete, contenu: { arm: { mecanise: { value: true, heritee: false, etapeHeritee: null } } } }, - 'arm', - demarcheIdValidator.parse('demarcheId'), - 'oct', + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), armDocuments, armEntrepriseDocuments, null, [], [], - { ...testBlankUser, role: 'super' }, - firstEtapeDateValidator.parse('2022-01-01') + { ...testBlankUser, role: 'super' } ) expect(errors).toMatchInlineSnapshot(` { @@ -668,10 +688,7 @@ test('isEtapeValide', () => { expect( isEtapeValid( { ...etapeComplete }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, - demarcheIdValidator.parse('fakeId'), - firstEtapeDateValidator.parse(etapeComplete.date) + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('fakeId'), firstEtapeDateValidator.parse(etapeComplete.date)) ) ).toMatchInlineSnapshot(` { @@ -682,10 +699,12 @@ test('isEtapeValide', () => { expect( isEtapeValid( { ...etapeComplete, date: DATE_DEBUT_PROCEDURE_SPECIFIQUE, typeId: ETAPES_TYPES.demande, duree: { value: 10 * 10, heritee: false, etapeHeritee: null } }, - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, - demarcheIdValidator.parse('fakeId'), - firstEtapeDateValidator.parse(DATE_DEBUT_PROCEDURE_SPECIFIQUE) + MachineInfo.withDate( + TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + DEMARCHES_TYPES_IDS.Octroi, + demarcheIdValidator.parse('fakeId'), + firstEtapeDateValidator.parse(DATE_DEBUT_PROCEDURE_SPECIFIQUE) + ) ) ).toMatchInlineSnapshot(` { @@ -715,16 +734,13 @@ test.each<[number | null, EtapeTypeId, TitreTypeId, IsEtapeCompleteDocuments, Is const result = isEtapeComplete( titreEtape, - titreType, - demarcheIdValidator.parse('demarcheId'), - 'oct', + MachineInfo.withDate(titreType, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), documents, entreprisedocuments, [], [], avis, - { ...testBlankUser, role: 'super' }, - firstEtapeDateValidator.parse('2022-01-01') + { ...testBlankUser, role: 'super' } ) const errorLabel = 'la durée est obligatoire pour une démarche octroi' @@ -744,40 +760,40 @@ describe('canDeposeEtape', () => { expect( canDeposeEtape( { ...testBlankUser, role: 'super' }, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), { - typeId: 'arm', titreStatutId: 'dmi', titulaires: [], administrationsLocales: [], }, - demarcheIdValidator.parse('demarcheId'), - 'oct', { ...etapeComplete, isBrouillon: ETAPE_IS_BROUILLON, contenu: { arm: { mecanise: { value: false, etapeHeritee: null, heritee: false } } } }, [...armDocuments], [...armEntrepriseDocuments], [], [], - [], - firstEtapeDateValidator.parse('2022-01-01') + [] ) ).toStrictEqual(true) }) }) describe('isEtapeDeposable', () => { + const machineInfo = MachineInfo.withDate( + TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + DEMARCHES_TYPES_IDS.Octroi, + demarcheIdValidator.parse('demarcheId'), + firstEtapeDateValidator.parse('2022-01-01') + ) test("Une demande d'ARM complète brouillon", () => { expect( isEtapeDeposable( { ...testBlankUser, role: 'super' }, - 'arm', - demarcheIdValidator.parse('demarcheId'), - 'oct', + machineInfo, { ...etapeComplete, isBrouillon: ETAPE_IS_BROUILLON, contenu: { arm: { mecanise: { value: false, etapeHeritee: null, heritee: false } } } }, armDocuments, armEntrepriseDocuments, [], [], - [], - firstEtapeDateValidator.parse('2022-01-01') + [] ) ).toStrictEqual(true) }) @@ -786,36 +802,21 @@ describe('isEtapeDeposable', () => { expect( isEtapeDeposable( { ...testBlankUser, role: 'super' }, - 'arm', - demarcheIdValidator.parse('demarcheId'), - 'oct', + machineInfo, { ...etapeComplete, isBrouillon: ETAPE_IS_NOT_BROUILLON, contenu: { arm: { mecanise: { value: false, etapeHeritee: null, heritee: false } } } }, armDocuments, armEntrepriseDocuments, [], [], - [], - firstEtapeDateValidator.parse('2022-01-01') + [] ) ).toStrictEqual(false) }) test("Une demande d'ARM incomplète", () => { - expect( - isEtapeDeposable( - { ...testBlankUser, role: 'super' }, - 'arm', - demarcheIdValidator.parse('demarcheId'), - 'oct', - { ...etapeComplete, isBrouillon: ETAPE_IS_BROUILLON }, - armDocuments, - armEntrepriseDocuments, - [], - [], - [], - firstEtapeDateValidator.parse('2022-01-01') - ) - ).toStrictEqual(false) + expect(isEtapeDeposable({ ...testBlankUser, role: 'super' }, machineInfo, { ...etapeComplete, isBrouillon: ETAPE_IS_BROUILLON }, armDocuments, armEntrepriseDocuments, [], [], [])).toStrictEqual( + false + ) }) }) @@ -838,13 +839,10 @@ describe('dureeIsValide', () => { demarcheTypeId, duree: dureeAnnees, dureeIsValide: dureeIsValide( - titreTypeId, - demarcheTypeId, + MachineInfo.withDate(titreTypeId, demarcheTypeId, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), ETAPES_TYPES.demande, { value: dureeAnnees !== null ? dureeAnnees * 12 : dureeAnnees }, - surface, - demarcheId, - firstEtapeDateValidator.parse(duringProcedureSpecifique) + surface ), }) }) @@ -941,7 +939,12 @@ describe('dureeIsValide', () => { result.push({ surface: km2toHectare(surface), duree: dureeAnnees, - dureeIsValide: dureeIsValide(titreTypeId, demarcheTypeId, ETAPES_TYPES.demande, { value: dureeAnnees * 12 }, surface, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), + dureeIsValide: dureeIsValide( + MachineInfo.withDate(titreTypeId, demarcheTypeId, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), + ETAPES_TYPES.demande, + { value: dureeAnnees * 12 }, + surface + ), }) }) }) @@ -963,7 +966,12 @@ describe('dureeIsValide', () => { result.push({ surface: km2toHectare(surface), duree: dureeAnnees, - dureeIsValide: dureeIsValide(titreTypeId, demarcheTypeId, ETAPES_TYPES.demande, { value: dureeAnnees * 12 }, surface, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), + dureeIsValide: dureeIsValide( + MachineInfo.withDate(titreTypeId, demarcheTypeId, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), + ETAPES_TYPES.demande, + { value: dureeAnnees * 12 }, + surface + ), }) }) }) @@ -1047,9 +1055,14 @@ describe('dureeIsValide', () => { surfaces.forEach(surface => { dureesAnnees.forEach(dureeAnnees => { - expect(dureeIsValide(titreTypeId, demarcheTypeId, ETAPES_TYPES.demande, { value: dureeAnnees * 12 }, surface, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)).valid).toBe( - true - ) + expect( + dureeIsValide( + MachineInfo.withDate(titreTypeId, demarcheTypeId, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), + ETAPES_TYPES.demande, + { value: dureeAnnees * 12 }, + surface + ).valid + ).toBe(true) }) }) }) @@ -1059,12 +1072,9 @@ describe('perimetreIsValide', () => { test('arm', () => { expect( perimetreIsValide( - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), ETAPES_TYPES.demande, - km2Validator.parse(1), - demarcheId, - firstEtapeDateValidator.parse(duringProcedureSpecifique) + km2Validator.parse(1) ) ).toMatchInlineSnapshot(` { @@ -1073,12 +1083,9 @@ describe('perimetreIsValide', () => { `) expect( perimetreIsValide( - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), ETAPES_TYPES.demande, - km2Validator.parse(3), - demarcheId, - firstEtapeDateValidator.parse(duringProcedureSpecifique) + km2Validator.parse(3) ) ).toMatchInlineSnapshot(` { @@ -1087,12 +1094,9 @@ describe('perimetreIsValide', () => { `) expect( perimetreIsValide( - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), ETAPES_TYPES.demande, - km2Validator.parse(4), - demarcheId, - firstEtapeDateValidator.parse(duringProcedureSpecifique) + km2Validator.parse(4) ) ).toMatchInlineSnapshot(` { @@ -1102,12 +1106,9 @@ describe('perimetreIsValide', () => { `) expect( perimetreIsValide( - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Prolongation, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Prolongation, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), ETAPES_TYPES.demande, - km2Validator.parse(4), - demarcheId, - firstEtapeDateValidator.parse(duringProcedureSpecifique) + km2Validator.parse(4) ) ).toMatchInlineSnapshot(` { @@ -1118,12 +1119,9 @@ describe('perimetreIsValide', () => { expect( perimetreIsValide( - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Prolongation, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Prolongation, demarcheId, firstEtapeDateValidator.parse(beforeProcedureSpecifiqueAxmArm)), ETAPES_TYPES.demande, - km2Validator.parse(4), - demarcheId, - firstEtapeDateValidator.parse(beforeProcedureSpecifiqueAxmArm) + km2Validator.parse(4) ) ).toMatchInlineSnapshot(` { @@ -1132,12 +1130,9 @@ describe('perimetreIsValide', () => { `) expect( perimetreIsValide( - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Prolongation, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Prolongation, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), ETAPES_TYPES.decisionDeLAutoriteAdministrative, - km2Validator.parse(4), - demarcheId, - firstEtapeDateValidator.parse(duringProcedureSpecifique) + km2Validator.parse(4) ) ).toMatchInlineSnapshot(` { @@ -1155,12 +1150,9 @@ describe('perimetreIsValide', () => { expect( perimetreIsValide( - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), ETAPES_TYPES.demande, - hectares_20, - demarcheId, - firstEtapeDateValidator.parse(duringProcedureSpecifique) + hectares_20 ) ).toMatchInlineSnapshot(` { @@ -1169,12 +1161,9 @@ describe('perimetreIsValide', () => { `) expect( perimetreIsValide( - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), ETAPES_TYPES.demande, - hectares_100, - demarcheId, - firstEtapeDateValidator.parse(duringProcedureSpecifique) + hectares_100 ) ).toMatchInlineSnapshot(` { @@ -1183,12 +1172,9 @@ describe('perimetreIsValide', () => { `) expect( perimetreIsValide( - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), ETAPES_TYPES.demande, - hectares_101, - demarcheId, - firstEtapeDateValidator.parse(duringProcedureSpecifique) + hectares_101 ) ).toMatchInlineSnapshot(` { @@ -1198,12 +1184,9 @@ describe('perimetreIsValide', () => { `) expect( perimetreIsValide( - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, - DEMARCHES_TYPES_IDS.Prolongation, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Prolongation, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), ETAPES_TYPES.demande, - hectares_20, - demarcheId, - firstEtapeDateValidator.parse(duringProcedureSpecifique) + hectares_20 ) ).toMatchInlineSnapshot(` { @@ -1212,12 +1195,9 @@ describe('perimetreIsValide', () => { `) expect( perimetreIsValide( - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, - DEMARCHES_TYPES_IDS.Prolongation, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Prolongation, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), ETAPES_TYPES.demande, - hectares_25, - demarcheId, - firstEtapeDateValidator.parse(duringProcedureSpecifique) + hectares_25 ) ).toMatchInlineSnapshot(` { @@ -1226,12 +1206,9 @@ describe('perimetreIsValide', () => { `) expect( perimetreIsValide( - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, - DEMARCHES_TYPES_IDS.Prolongation, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Prolongation, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), ETAPES_TYPES.demande, - hectares_26, - demarcheId, - firstEtapeDateValidator.parse(duringProcedureSpecifique) + hectares_26 ) ).toMatchInlineSnapshot(` { @@ -1242,12 +1219,9 @@ describe('perimetreIsValide', () => { expect( perimetreIsValide( - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, - DEMARCHES_TYPES_IDS.RenonciationTotale, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.RenonciationTotale, demarcheId, firstEtapeDateValidator.parse(duringProcedureSpecifique)), ETAPES_TYPES.demande, - hectares_100, - demarcheId, - firstEtapeDateValidator.parse(duringProcedureSpecifique) + hectares_100 ) ).toMatchInlineSnapshot(` { diff --git a/packages/common/src/permissions/titres-etapes.ts b/packages/common/src/permissions/titres-etapes.ts index 243d46512..370e14de4 100644 --- a/packages/common/src/permissions/titres-etapes.ts +++ b/packages/common/src/permissions/titres-etapes.ts @@ -25,18 +25,16 @@ import { DemarcheTypeId, DEMARCHES_TYPES_IDS, DemarchesTypes, isDemarcheTypeProl import { EtapeTypeId, ETAPES_TYPES, EtapesTypes, isEtapeDecision } from '../static/etapesTypes' import { TITRES_TYPES_IDS_DEMAT } from './titres' import { KM2, km2toHectare, ZERO_KM2 } from '../number' -import { machineIdFind } from '../machines' -import { DemarcheId } from '../demarche' -import { FirstEtapeDate } from '../date' +import { MachineInfo } from '../machines' export type InputAbsent = { visibility: 'absent'; message: string } type InputPresentRequired = { visibility: 'present'; required: true; message: string } export type InputPresentOptional = { visibility: 'present'; required: false } export type InputPresence = InputAbsent | InputPresentRequired | InputPresentOptional -export const canEditAmodiataires = (titreTypeId: TitreTypeId, demarcheTypeId: DemarcheTypeId, user: User): InputPresence => { - if (titreTypeId === TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX || titreTypeId === TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX) { - return { visibility: 'absent', message: `une autorisation ${titreTypeId === 'arm' ? 'de recherche' : "d'exploitation"} ne peut pas inclure d'amodiataires` } +export const canEditAmodiataires = (machineInfo: MachineInfo, user: User): InputPresence => { + if (machineInfo.titreTypeId === TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX || machineInfo.titreTypeId === TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX) { + return { visibility: 'absent', message: `une autorisation ${machineInfo.titreTypeId === 'arm' ? 'de recherche' : "d'exploitation"} ne peut pas inclure d'amodiataires` } } if ( @@ -49,14 +47,14 @@ export const canEditAmodiataires = (titreTypeId: TitreTypeId, demarcheTypeId: De DEMARCHES_TYPES_IDS.Conversion, DEMARCHES_TYPES_IDS.ExtensionDePerimetre, DEMARCHES_TYPES_IDS.ResiliationAnticipeeDAmodiation, - ].includes(demarcheTypeId) + ].includes(machineInfo.demarcheTypeId) ) { - return { visibility: 'absent', message: `une démarche ${DemarchesTypes[demarcheTypeId].nom} ne peut pas inclure d'amodiataire` } + return { visibility: 'absent', message: `une démarche ${DemarchesTypes[machineInfo.demarcheTypeId].nom} ne peut pas inclure d'amodiataire` } } // seuls les supers et les administrations peuvent éditer les amodiataires if (isSuper(user) || isAdministrationAdmin(user) || isAdministrationEditeur(user)) { - if (demarcheTypeId === DEMARCHES_TYPES_IDS.Amodiation) { + if (machineInfo.demarcheTypeId === DEMARCHES_TYPES_IDS.Amodiation) { return { visibility: 'present', required: true, message: "les amodiataires sont obligatoires pour les démarches d'Amodiation" } } @@ -69,9 +67,9 @@ export const canEditAmodiataires = (titreTypeId: TitreTypeId, demarcheTypeId: De const demarchesSansDatesNiDureePourLesEtapes = [DEMARCHES_TYPES_IDS.Mutation, DEMARCHES_TYPES_IDS.ExtensionDePerimetre] as const // Attention les champs dates ne sont jamais obligatoires, si ils le deviennent il faudra faire des modifs dans la validation et dans l'ui -export const canEditDates = (_titreTypeId: TitreTypeId, demarcheTypeId: DemarcheTypeId, etapeTypeId: EtapeTypeId, user: User): InputAbsent | InputPresentOptional => { - if (demarchesSansDatesNiDureePourLesEtapes.includes(demarcheTypeId)) { - return { visibility: 'absent', message: `une démarche ${DemarchesTypes[demarcheTypeId].nom} ne peut pas inclure de date` } +export const canEditDates = (machineInfo: MachineInfo, etapeTypeId: EtapeTypeId, user: User): InputAbsent | InputPresentOptional => { + if (demarchesSansDatesNiDureePourLesEtapes.includes(machineInfo.demarcheTypeId)) { + return { visibility: 'absent', message: `une démarche ${DemarchesTypes[machineInfo.demarcheTypeId].nom} ne peut pas inclure de date` } } if (!isEtapeDecision(etapeTypeId)) { @@ -85,7 +83,7 @@ export const canEditDates = (_titreTypeId: TitreTypeId, demarcheTypeId: Demarche return { visibility: 'absent', message: 'droits insuffisants pour éditer les dates' } } -export const canEditTitulaires = (_titreTypeId: TitreTypeId, demarcheTypeId: DemarcheTypeId, user: User): InputPresence => { +export const canEditTitulaires = (machineInfo: MachineInfo, user: User): InputPresence => { if ( [ DEMARCHES_TYPES_IDS.Fusion, @@ -95,39 +93,35 @@ export const canEditTitulaires = (_titreTypeId: TitreTypeId, demarcheTypeId: Dem DEMARCHES_TYPES_IDS.Conversion, DEMARCHES_TYPES_IDS.ExtensionDePerimetre, DEMARCHES_TYPES_IDS.ResiliationAnticipeeDAmodiation, - ].includes(demarcheTypeId) + ].includes(machineInfo.demarcheTypeId) ) { - return { visibility: 'absent', message: `une démarche ${DemarchesTypes[demarcheTypeId].nom} ne peut pas inclure de titulaire` } + return { visibility: 'absent', message: `une démarche ${DemarchesTypes[machineInfo.demarcheTypeId].nom} ne peut pas inclure de titulaire` } } // seuls les supers et les administrations peuvent éditer les titulaires if (isSuper(user) || isAdministrationAdmin(user) || isAdministrationEditeur(user)) { - return { visibility: 'present', required: true, message: `les titulaires sont obligatoires pour les démarches ${DemarchesTypes[demarcheTypeId].nom}` } + return { visibility: 'present', required: true, message: `les titulaires sont obligatoires pour les démarches ${DemarchesTypes[machineInfo.demarcheTypeId].nom}` } } return { visibility: 'absent', message: 'droits insuffisants pour éditer les titulaires' } } export const dureeIsValide = ( - titreTypeId: TitreTypeId, - demarcheTypeId: DemarcheTypeId, + machineInfo: MachineInfo, etapeTypeId: EtapeTypeId, dureeValue: Pick<FlattenEtape['duree'], 'value'>, - surfaceKm2: KM2, - demarcheId: DemarcheId, - date: FirstEtapeDate + surfaceKm2: KM2 ): { valid: true } | { valid: false; message: string } => { - const machineId = machineIdFind(titreTypeId, demarcheTypeId, demarcheId, date) - if (etapeTypeId === ETAPES_TYPES.demande && machineId === 'ProcedureSpecifique') { + if (etapeTypeId === ETAPES_TYPES.demande && machineInfo.machineId === 'ProcedureSpecifique') { const duree = dureeValue.value ?? 0 const surface = km2toHectare(surfaceKm2) - if (titreTypeId === TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX && demarcheTypeId === DEMARCHES_TYPES_IDS.Octroi && duree > 2 * 12) { + if (machineInfo.titreTypeId === TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX && machineInfo.demarcheTypeId === DEMARCHES_TYPES_IDS.Octroi && duree > 2 * 12) { return { valid: false, message: `Un octroi d'ARM ne peut pas dépasser 2 ans` } } - if (titreTypeId === TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX) { - if (demarcheTypeId === DEMARCHES_TYPES_IDS.Octroi) { + if (machineInfo.titreTypeId === TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX) { + if (machineInfo.demarcheTypeId === DEMARCHES_TYPES_IDS.Octroi) { if (surface <= 25 && duree > 4 * 12) { return { valid: false, message: `Un octroi d'AEX inférieur ou égal à 25 hectares ne peut pas dépasser 4 ans` } } @@ -135,7 +129,7 @@ export const dureeIsValide = ( return { valid: false, message: `Un octroi d'AEX supérieur à 25 hectares et inférieur ou égal à 100 hectares ne peut pas dépasser 10 ans` } } } - if (isDemarcheTypeProlongations(demarcheTypeId)) { + if (isDemarcheTypeProlongations(machineInfo.demarcheTypeId)) { if (surface <= 25 && duree > 4 * 12) { return { valid: false, message: `Une prolongation d'AEX inférieure ou égale à 25 hectares ne peut pas dépasser 4 ans` } } @@ -146,39 +140,31 @@ export const dureeIsValide = ( return { valid: true } } -export const canEditDuree = (_titreTypeId: TitreTypeId, demarcheTypeId: DemarcheTypeId, _user: User): InputPresence => { +export const canEditDuree = (machineInfo: MachineInfo, _user: User): InputPresence => { // par exemple, ne peut pas ajouter de durée à la démarche déplacement de périmètre - if (demarchesSansDatesNiDureePourLesEtapes.includes(demarcheTypeId)) { - return { visibility: 'absent', message: `une démarche ${DemarchesTypes[demarcheTypeId].nom} ne peut pas inclure de durée` } + if (demarchesSansDatesNiDureePourLesEtapes.includes(machineInfo.demarcheTypeId)) { + return { visibility: 'absent', message: `une démarche ${DemarchesTypes[machineInfo.demarcheTypeId].nom} ne peut pas inclure de durée` } } - return { visibility: 'present', required: true, message: `la durée est obligatoire pour une démarche ${DemarchesTypes[demarcheTypeId].nom}` } + return { visibility: 'present', required: true, message: `la durée est obligatoire pour une démarche ${DemarchesTypes[machineInfo.demarcheTypeId].nom}` } } -export const perimetreIsValide = ( - titreTypeId: TitreTypeId, - demarcheTypeId: DemarcheTypeId, - etapeTypeId: EtapeTypeId, - surfaceKm2: KM2, - demarcheId: DemarcheId, - date: FirstEtapeDate -): { valid: true } | { valid: false; message: string } => { - const machineId = machineIdFind(titreTypeId, demarcheTypeId, demarcheId, date) - if (etapeTypeId === ETAPES_TYPES.demande && machineId === 'ProcedureSpecifique') { +export const perimetreIsValide = (machineInfo: MachineInfo, etapeTypeId: EtapeTypeId, surfaceKm2: KM2): { valid: true } | { valid: false; message: string } => { + if (etapeTypeId === ETAPES_TYPES.demande && machineInfo.machineId === 'ProcedureSpecifique') { const surface = km2toHectare(surfaceKm2) - if (titreTypeId === TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX) { + if (machineInfo.titreTypeId === TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX) { if (surfaceKm2 > 3) { return { valid: false, message: `Une ARM supérieure à 3km² est interdit` } } } - if (titreTypeId === TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX) { - if (demarcheTypeId === DEMARCHES_TYPES_IDS.Octroi) { + if (machineInfo.titreTypeId === TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX) { + if (machineInfo.demarcheTypeId === DEMARCHES_TYPES_IDS.Octroi) { if (surface > 100) { return { valid: false, message: `Un octroi d'AEX supérieur à 100 hectares est interdit` } } } - if (isDemarcheTypeProlongations(demarcheTypeId)) { + if (isDemarcheTypeProlongations(machineInfo.demarcheTypeId)) { if (surface > 25) { return { valid: false, message: `Une prolongation d'AEX supérieure à 25 hectares est interdit` } } @@ -188,7 +174,7 @@ export const perimetreIsValide = ( return { valid: true } } -export const canEditPerimetre = (demarcheTypeId: DemarcheTypeId, etapeTypeId: EtapeTypeId): InputPresence => { +export const canEditPerimetre = (machineInfo: MachineInfo, etapeTypeId: EtapeTypeId): InputPresence => { if (!EtapesTypes[etapeTypeId].fondamentale) { return { visibility: 'absent', message: `une étape ${EtapesTypes[etapeTypeId].nom} ne peut pas inclure de périmètre` } } @@ -201,12 +187,12 @@ export const canEditPerimetre = (demarcheTypeId: DemarcheTypeId, etapeTypeId: Et DEMARCHES_TYPES_IDS.Amodiation, DEMARCHES_TYPES_IDS.Conversion, DEMARCHES_TYPES_IDS.ResiliationAnticipeeDAmodiation, - ].includes(demarcheTypeId) + ].includes(machineInfo.demarcheTypeId) ) { - return { visibility: 'absent', message: `une démarche ${DemarchesTypes[demarcheTypeId].nom} ne peut pas inclure de périmètre` } + return { visibility: 'absent', message: `une démarche ${DemarchesTypes[machineInfo.demarcheTypeId].nom} ne peut pas inclure de périmètre` } } - return { visibility: 'present', required: true, message: `le périmètre est obligatoire pour une démarche ${DemarchesTypes[demarcheTypeId].nom}` } + return { visibility: 'present', required: true, message: `le périmètre est obligatoire pour une démarche ${DemarchesTypes[machineInfo.demarcheTypeId].nom}` } } export const canCreateEtape = ( @@ -283,18 +269,9 @@ type IsEtapeCompleteSdomZones = SDOMZoneId[] | null | undefined type IsEtapeCompleteCommunes = CommuneId[] export type IsEtapeCompleteEtapeAvis = Pick<EtapeAvis, 'avis_type_id'>[] -export const isEtapeValid = ( - etape: IsEtapeCompleteEtape, - titreTypeId: TitreTypeId, - demarcheTypeId: DemarcheTypeId, - demarcheId: DemarcheId, - firstEtapeDate: FirstEtapeDate -): { valid: true } | { valid: false; errors: NonEmptyArray<string> } => { +export const isEtapeValid = (etape: IsEtapeCompleteEtape, machineInfo: MachineInfo): { valid: true } | { valid: false; errors: NonEmptyArray<string> } => { const surface = etape.perimetre.value?.surface ?? ZERO_KM2 - const isValidChecks = [ - dureeIsValide(titreTypeId, demarcheTypeId, etape.typeId, etape.duree, surface, demarcheId, firstEtapeDate), - perimetreIsValide(titreTypeId, demarcheTypeId, etape.typeId, surface, demarcheId, firstEtapeDate), - ] + const isValidChecks = [dureeIsValide(machineInfo, etape.typeId, etape.duree, surface), perimetreIsValide(machineInfo, etape.typeId, surface)] const errors: string[] = isValidChecks.reduce<string[]>((acc, c) => { if (!c.valid) { acc.push(c.message) @@ -312,30 +289,26 @@ export const isEtapeValid = ( export const isEtapeComplete = ( etape: IsEtapeCompleteEtape, - titreTypeId: TitreTypeId, - demarcheId: DemarcheId, - demarcheTypeId: DemarcheTypeId, + machineInfo: MachineInfo, documents: IsEtapeCompleteDocuments, entrepriseDocuments: IsEtapeCompleteEntrepriseDocuments, sdomZones: IsEtapeCompleteSdomZones, communes: IsEtapeCompleteCommunes, etapeAvis: IsEtapeCompleteEtapeAvis, - user: User, - firstEtapeDate: FirstEtapeDate + user: User ): { valid: true; errors: null } | { valid: false; errors: NonEmptyArray<string> } => { const isCompleteChecks = [ dateTypeStepIsComplete(etape, user), - fondamentaleStepIsComplete(etape, demarcheTypeId, titreTypeId, user), - sectionsStepIsComplete(etape, demarcheTypeId, titreTypeId), - perimetreStepIsComplete(etape, demarcheTypeId), - etapeDocumentsStepIsComplete(etape, demarcheTypeId, titreTypeId, demarcheId, documents, sdomZones ?? [], firstEtapeDate), + fondamentaleStepIsComplete(etape, machineInfo, user), + sectionsStepIsComplete(etape, machineInfo), + perimetreStepIsComplete(etape, machineInfo), + etapeDocumentsStepIsComplete(etape, machineInfo, documents, sdomZones ?? []), entrepriseDocumentsStepIsComplete( etape, - demarcheTypeId, - titreTypeId, + machineInfo, entrepriseDocuments.map(ed => ({ documentTypeId: ed.entreprise_document_type_id, entrepriseId: ed.entreprise_id })) ), - etapeAvisStepIsComplete(etape, etapeAvis, titreTypeId, demarcheTypeId, demarcheId, firstEtapeDate, communes), + etapeAvisStepIsComplete(etape, etapeAvis, machineInfo, communes), ] const errors: string[] = isCompleteChecks.reduce<string[]>((acc, c) => { if (!c.valid) { @@ -355,19 +328,16 @@ export const isEtapeComplete = ( type IsEtapeDeposableEtapeAvis = Pick<EtapeAvis | TempEtapeAvis, 'avis_type_id'>[] export const isEtapeDeposable = ( user: User, - titreTypeId: TitreTypeId, - demarcheId: DemarcheId, - demarcheTypeId: DemarcheTypeId, + machineInfo: MachineInfo, titreEtape: Pick<FlattenEtape, 'typeId' | 'date' | 'statutId' | 'duree' | 'contenu' | 'substances' | 'perimetre' | 'isBrouillon' | 'titulaires' | 'amodiataires'>, etapeDocuments: IsEtapeCompleteDocuments, entrepriseDocuments: IsEtapeCompleteEntrepriseDocuments, sdomZones: IsEtapeCompleteSdomZones, communes: IsEtapeCompleteCommunes, - etapeAvis: IsEtapeDeposableEtapeAvis, - firstEtapeDate: FirstEtapeDate + etapeAvis: IsEtapeDeposableEtapeAvis ): boolean => { if (titreEtape.isBrouillon === ETAPE_IS_BROUILLON) { - const complete = isEtapeComplete(titreEtape, titreTypeId, demarcheId, demarcheTypeId, etapeDocuments, entrepriseDocuments, sdomZones, communes, etapeAvis, user, firstEtapeDate) + const complete = isEtapeComplete(titreEtape, machineInfo, etapeDocuments, entrepriseDocuments, sdomZones, communes, etapeAvis, user) if (!complete.valid) { console.warn(complete.errors) @@ -382,32 +352,29 @@ export const isEtapeDeposable = ( export const canDeposeEtape = ( user: User, + machineInfo: MachineInfo, titre: { - typeId: TitreTypeId titreStatutId: TitreStatutId titulaires: EntrepriseId[] administrationsLocales: AdministrationId[] }, - demarcheId: DemarcheId, - demarcheTypeId: DemarcheTypeId, titreEtape: Pick<FlattenEtape, 'typeId' | 'date' | 'statutId' | 'duree' | 'contenu' | 'substances' | 'perimetre' | 'isBrouillon' | 'titulaires' | 'amodiataires'>, etapeDocuments: Pick<EtapeDocument, 'etape_document_type_id'>[], entrepriseDocuments: Pick<EntrepriseDocument, 'entreprise_document_type_id' | 'entreprise_id'>[], sdomZones: SDOMZoneId[] | null | undefined, communes: CommuneId[], - etapeAvis: IsEtapeDeposableEtapeAvis, - firstEtapeDate: FirstEtapeDate + etapeAvis: IsEtapeDeposableEtapeAvis ): boolean => { return ( - isEtapeDeposable(user, titre.typeId, demarcheId, demarcheTypeId, titreEtape, etapeDocuments, entrepriseDocuments, sdomZones, communes, etapeAvis, firstEtapeDate) && + isEtapeDeposable(user, machineInfo, titreEtape, etapeDocuments, entrepriseDocuments, sdomZones, communes, etapeAvis) && canCreateOrEditEtape( user, titreEtape.typeId, titreEtape.isBrouillon, titre.titulaires, titre.administrationsLocales, - demarcheTypeId, - { typeId: titre.typeId, titreStatutId: titre.titreStatutId }, + machineInfo.demarcheTypeId, + { typeId: machineInfo.titreTypeId, titreStatutId: titre.titreStatutId }, 'modification' ) ) diff --git a/packages/common/src/permissions/titres.test.ts b/packages/common/src/permissions/titres.test.ts index 3871a67dc..444e44594 100644 --- a/packages/common/src/permissions/titres.test.ts +++ b/packages/common/src/permissions/titres.test.ts @@ -10,7 +10,7 @@ import { canSeeTitreLastModifiedDate, getLinkConfig, } from './titres' -import { TitresTypesIds, TitreTypeId } from '../static/titresTypes' +import { TITRES_TYPES_IDS, TitresTypesIds, TitreTypeId } from '../static/titresTypes' import { ADMINISTRATION_IDS, AdministrationId } from '../static/administrations' import { test, expect, describe } from 'vitest' import { testBlankUser, TestUser } from '../tests-utils' @@ -20,6 +20,10 @@ import { ACTIVITES_TYPES_IDS } from '../static/activitesTypes' import { toCommuneId } from '../static/communes' import { TitreStatutId, titresStatutsArray } from '../static/titresStatuts' import { isAssociee, isGestionnaire } from '../static/administrationsTitresTypes' +import { MachineInfo } from '../machines' +import { DEMARCHES_TYPES_IDS } from '../static/demarchesTypes' +import { firstEtapeDateValidator } from '../date' +import { demarcheIdValidator } from '../demarche' const shouldNotBeCalled = () => Promise.reject(new Error('should not be called')) @@ -44,8 +48,16 @@ test('canHaveActivites', () => { }) test('canHaveForages', () => { - expect(canHaveForages('apc')).toBe(false) - expect(canHaveForages('pxg')).toBe(true) + expect( + canHaveForages( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_CARRIERES, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01')) + ) + ).toBe(false) + expect( + canHaveForages( + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_GEOTHERMIE, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01')) + ) + ).toBe(true) }) test('getTitreFromTypeId pas de fusions', () => { diff --git a/packages/common/src/permissions/titres.ts b/packages/common/src/permissions/titres.ts index 12f134873..0d0d0df5d 100644 --- a/packages/common/src/permissions/titres.ts +++ b/packages/common/src/permissions/titres.ts @@ -14,6 +14,7 @@ import { isNotNullNorUndefinedNorEmpty, isNullOrUndefinedOrEmpty, SimplePromiseF import { SecteursMaritimes } from '../static/facades' import { EntrepriseId } from '../entreprise' import { TITRES_TYPES_TYPES_IDS } from '../static/titresTypesTypes' +import { MachineInfo } from '../machines' export const canSeeTitreLastModifiedDate = (user: User): boolean => isSuper(user) || isAdministration(user) export type LinkConfig = { count: 'single' | 'multiple'; typeId: TitreTypeId } @@ -150,4 +151,4 @@ export const canHaveActiviteTypeId = (activiteTypeId: ActivitesTypesId, titre: T return false } -export const canHaveForages = (titreTypeId: TitreTypeId): boolean => titreTypeId === 'pxg' +export const canHaveForages = (machineInfo: MachineInfo): boolean => machineInfo.titreTypeId === TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_GEOTHERMIE diff --git a/packages/common/src/sections.test.ts b/packages/common/src/sections.test.ts index 3d5285cfe..bede292e1 100644 --- a/packages/common/src/sections.test.ts +++ b/packages/common/src/sections.test.ts @@ -1,6 +1,11 @@ import { test, expect } from 'vitest' import { flattenContenuToSimpleContenu, isRadioElement, simpleContenuToFlattenedContenu, valeurFind } from './sections' -import { caminoDateValidator, toCaminoDate } from './date' +import { caminoDateValidator, firstEtapeDateValidator, toCaminoDate } from './date' +import { MachineInfo } from './machines' +import { TITRES_TYPES_IDS } from './static/titresTypes' +import { DEMARCHES_TYPES_IDS } from './static/demarchesTypes' +import { ETAPES_TYPES } from './static/etapesTypes' +import { demarcheIdValidator } from './demarche' test('valeurFind', () => { expect(valeurFind({ id: 'camino', type: 'text', value: null, optionnel: false })).toBe('–') @@ -81,11 +86,10 @@ test('isRadioElement', () => { test('simpleContenuToFlattenedContenu', () => { expect( simpleContenuToFlattenedContenu( - 'arm', - 'oct', - 'mfr', + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01')), + ETAPES_TYPES.demande, { arm: { mecanise: true } }, - { arm: { mecanise: { actif: true, etape: { date: caminoDateValidator.parse('2023-02-02'), typeId: 'mfr', contenu: { arm: { mecanise: false } } } } } } + { arm: { mecanise: { actif: true, etape: { date: caminoDateValidator.parse('2023-02-02'), typeId: ETAPES_TYPES.demande, contenu: { arm: { mecanise: false } } } } } } ) ).toMatchInlineSnapshot(` { @@ -109,11 +113,10 @@ test('simpleContenuToFlattenedContenu', () => { `) expect( simpleContenuToFlattenedContenu( - 'arm', - 'oct', - 'mfr', + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01')), + ETAPES_TYPES.demande, { arm: { mecanise: true } }, - { arm: { mecanise: { actif: false, etape: { date: caminoDateValidator.parse('2023-02-02'), typeId: 'mfr', contenu: { arm: { mecanise: false } } } } } } + { arm: { mecanise: { actif: false, etape: { date: caminoDateValidator.parse('2023-02-02'), typeId: ETAPES_TYPES.demande, contenu: { arm: { mecanise: false } } } } } } ) ).toMatchInlineSnapshot(` { @@ -137,11 +140,10 @@ test('simpleContenuToFlattenedContenu', () => { `) expect( simpleContenuToFlattenedContenu( - 'arm', - 'oct', - 'mfr', + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01')), + ETAPES_TYPES.demande, { arm: {} }, - { arm: { mecanise: { actif: true, etape: { date: caminoDateValidator.parse('2023-02-02'), typeId: 'mfr', contenu: { arm: {} } } } } } + { arm: { mecanise: { actif: true, etape: { date: caminoDateValidator.parse('2023-02-02'), typeId: ETAPES_TYPES.demande, contenu: { arm: {} } } } } } ) ).toMatchInlineSnapshot(` { @@ -178,7 +180,7 @@ test('flattenContenuToSimpleContenu', () => { mecanise: { etapeHeritee: { date: toCaminoDate('2023-02-02'), - etapeTypeId: 'mfr', + etapeTypeId: ETAPES_TYPES.demande, value: false, }, heritee: false, diff --git a/packages/common/src/sections.ts b/packages/common/src/sections.ts index 423156187..e90df4632 100644 --- a/packages/common/src/sections.ts +++ b/packages/common/src/sections.ts @@ -13,10 +13,9 @@ import { } from './static/titresTypes_demarchesTypes_etapesTypes/sections' import { z } from 'zod' import { isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty } from './typescript-tools' -import { TitreTypeId } from './static/titresTypes' -import { DemarcheTypeId } from './static/demarchesTypes' import { EtapeTypeId } from './static/etapesTypes' import { EtapeContenu, FlattenEtape, FlattenedContenu, RestEtapeCreation, HeritageContenu } from './etape-form' +import { MachineInfo } from './machines' const dateElementWithValueValidator = dateElementValidator.extend({ value: caminoDateValidator.nullable() }) @@ -99,14 +98,8 @@ export const valeurFind = (element: ElementWithValue): string | '–' => { return element.value } -export const simpleContenuToFlattenedContenu = ( - titreTypeId: TitreTypeId, - demarcheTypeId: DemarcheTypeId, - etapeTypeId: EtapeTypeId, - contenu: EtapeContenu, - heritageContenu: HeritageContenu -): FlattenedContenu => { - const sections = getSections(titreTypeId, demarcheTypeId, etapeTypeId) +export const simpleContenuToFlattenedContenu = (machineInfo: MachineInfo, etapeTypeId: EtapeTypeId, contenu: EtapeContenu, heritageContenu: HeritageContenu): FlattenedContenu => { + const sections = getSections(machineInfo, etapeTypeId) return sections.reduce<FlattenedContenu>((accSection, section) => { accSection[section.id] = section.elements.reduce<NonNullable<FlattenedContenu[string]>>((accElement, element) => { diff --git a/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/documents.test.ts b/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/documents.test.ts index ec36bb473..a4744369b 100644 --- a/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/documents.test.ts +++ b/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/documents.test.ts @@ -1,5 +1,6 @@ import { firstEtapeDateValidator } from '../../date' import { demarcheIdValidator } from '../../demarche' +import { MachineInfo } from '../../machines' import { DEMARCHES_TYPES_IDS } from '../demarchesTypes' import { ETAPES_TYPES } from '../etapesTypes' import { IS_ARM_MECANISE, IS_ARM_NON_MECANISE } from '../mecanise' @@ -14,7 +15,14 @@ test('toDocuments', () => { const firstEtapeDate = firstEtapeDateValidator.parse('2020-11-01') const demarcheId = demarcheIdValidator.parse('id1Demarche') test('getDocuments pas de surcharge mais pas de documents', () => { - expect(getDocuments('apm', 'amo', 'pqr', firstEtapeDate, demarcheId, [], IS_ARM_NON_MECANISE)).toMatchInlineSnapshot(` + expect( + getDocuments( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_METAUX, DEMARCHES_TYPES_IDS.Amodiation, demarcheId, firstEtapeDate), + ETAPES_TYPES.publicationDansUnJournalLocalOuNational, + [], + IS_ARM_NON_MECANISE + ) + ).toMatchInlineSnapshot(` [ { "id": "aut", @@ -26,7 +34,14 @@ test('getDocuments pas de surcharge mais pas de documents', () => { }) test('getDocuments pas de surcharge', () => { - expect(getDocuments('apm', 'amo', 'wfo', firstEtapeDate, demarcheId, [], IS_ARM_NON_MECANISE)).toMatchInlineSnapshot(` + expect( + getDocuments( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_METAUX, DEMARCHES_TYPES_IDS.Amodiation, demarcheId, firstEtapeDate), + ETAPES_TYPES.declarationDouvertureDeTravauxMiniers_DOTM_, + [], + IS_ARM_NON_MECANISE + ) + ).toMatchInlineSnapshot(` [ { "id": "dcl", @@ -43,19 +58,22 @@ test('getDocuments pas de surcharge', () => { }) test('getDocuments surcharge', () => { - expect(getDocuments('axm', 'oct', 'mfr', firstEtapeDate, demarcheId, [], IS_ARM_NON_MECANISE)).toMatchSnapshot() + expect( + getDocuments(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), ETAPES_TYPES.demande, [], IS_ARM_NON_MECANISE) + ).toMatchSnapshot() - expect(getDocuments('axm', 'oct', 'mfr', firstEtapeDate, demarcheId, [], IS_ARM_NON_MECANISE)).not.toEqual(getDocuments('axm', 'ces', 'mfr', firstEtapeDate, demarcheId, [], IS_ARM_NON_MECANISE)) + expect( + getDocuments(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), ETAPES_TYPES.demande, [], IS_ARM_NON_MECANISE) + ).not.toEqual( + getDocuments(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Cession, demarcheId, firstEtapeDate), ETAPES_TYPES.demande, [], IS_ARM_NON_MECANISE) + ) }) test("la lettre des saisines est obligatoire pour l'avis des services et commissions consultatives", () => { expect( getDocuments( - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, - firstEtapeDate, - demarcheId, [], IS_ARM_NON_MECANISE ) @@ -78,11 +96,8 @@ test("la lettre des saisines est obligatoire pour l'avis des services et commiss test("le courrier de notification au préfet est obligatoire pour l'information du préfet et des collectivités", () => { expect( getDocuments( - TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), ETAPES_TYPES.informationDuPrefetEtDesCollectivites, - firstEtapeDate, - demarcheId, [], IS_ARM_NON_MECANISE ) @@ -105,11 +120,8 @@ test("le courrier de notification au préfet est obligatoire pour l'information test('getDocuments', () => { expect( getDocuments( - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), ETAPES_TYPES.consultationDesAdministrationsCentrales, - firstEtapeDateValidator.parse('2022-01-01'), - demarcheIdValidator.parse('demarcheId'), [], IS_ARM_NON_MECANISE ) @@ -130,11 +142,8 @@ test('getDocuments', () => { expect( getDocuments( - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), ETAPES_TYPES.demande, - firstEtapeDateValidator.parse('2022-01-01'), - demarcheIdValidator.parse('demarcheId'), [], IS_ARM_NON_MECANISE ) @@ -241,11 +250,8 @@ test('getDocuments', () => { expect( getDocuments( - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), ETAPES_TYPES.demande, - firstEtapeDateValidator.parse('2022-01-01'), - demarcheIdValidator.parse('demarcheId'), [], IS_ARM_MECANISE ) @@ -351,11 +357,8 @@ test('getDocuments', () => { `) expect( getDocuments( - TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2024-10-01')), ETAPES_TYPES.demande, - firstEtapeDateValidator.parse('2024-10-01'), - demarcheIdValidator.parse('demarcheId'), [], IS_ARM_MECANISE ) @@ -461,33 +464,24 @@ test('getDocuments', () => { `) expect( getDocuments( - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), ETAPES_TYPES.demande, - firstEtapeDateValidator.parse('2022-01-01'), - demarcheIdValidator.parse('demarcheId'), ['1'], IS_ARM_NON_MECANISE ) ).toMatchSnapshot() expect( getDocuments( - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2022-01-01')), ETAPES_TYPES.demande, - firstEtapeDateValidator.parse('2022-01-01'), - demarcheIdValidator.parse('demarcheId'), ['2'], IS_ARM_NON_MECANISE ) ).toMatchSnapshot() expect( getDocuments( - TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, - DEMARCHES_TYPES_IDS.Octroi, + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2024-12-01')), ETAPES_TYPES.demande, - firstEtapeDateValidator.parse('2024-12-01'), - demarcheIdValidator.parse('demarcheId'), ['2'], IS_ARM_NON_MECANISE ) diff --git a/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/documents.ts b/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/documents.ts index 9482cba73..012777e33 100644 --- a/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/documents.ts +++ b/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/documents.ts @@ -1,6 +1,4 @@ -import { FirstEtapeDate } from '../../date' -import { DemarcheId } from '../../demarche' -import { isProcedureOuverte, machineIdFind } from '../../machines' +import { isProcedureOuverte, MachineInfo } from '../../machines' import { getEntriesHardcore, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty } from '../../typescript-tools' import { IS_ARM_MECANISE, IsArmMecanise } from '../mecanise' import { SDOMZoneId } from '../sdom' @@ -359,26 +357,17 @@ export const toDocuments = (): ToDocument[] => { values.map(value => ({ etapeTypeId: key, documentTypeId: value.documentTypeId, description: null, optionnel: value.optionnel })) ) } -export const getDocuments = ( - titreTypeId: TitreTypeId, - demarcheTypeId: DemarcheTypeId, - etapeTypeId: EtapeTypeId, - firstEtapeDate: FirstEtapeDate, - demarcheId: DemarcheId, - sdomZoneIds: SDOMZoneId[], - isArmMecanise: IsArmMecanise -): (DocumentType | AutreDocumentType)[] => { +export const getDocuments = (machineInfo: MachineInfo, etapeTypeId: EtapeTypeId, sdomZoneIds: SDOMZoneId[], isArmMecanise: IsArmMecanise): (DocumentType | AutreDocumentType)[] => { const documentTypes: (DocumentType | AutreDocumentType)[] = [] - const machineId = machineIdFind(titreTypeId, demarcheTypeId, demarcheId, firstEtapeDate) if (isEtapesTypesEtapesTypesDocumentsTypes(etapeTypeId)) { documentTypes.push(...EtapesTypesDocumentsTypes[etapeTypeId].map(({ documentTypeId, optionnel }) => ({ ...DocumentsTypes[documentTypeId], optionnel }))) } - Object.keys((TDEDocumentsTypes as TDEDocumentsTypesUnleashed)[titreTypeId]?.[demarcheTypeId]?.[etapeTypeId] ?? {}) + Object.keys((TDEDocumentsTypes as TDEDocumentsTypesUnleashed)[machineInfo.titreTypeId]?.[machineInfo.demarcheTypeId]?.[etapeTypeId] ?? {}) .filter(isDocumentTypeId) .forEach(documentTypeIdSpecifique => { - const documentSpecifique = (TDEDocumentsTypes as TDEDocumentsTypesUnleashed)[titreTypeId]?.[demarcheTypeId]?.[etapeTypeId]?.[documentTypeIdSpecifique] + const documentSpecifique = (TDEDocumentsTypes as TDEDocumentsTypesUnleashed)[machineInfo.titreTypeId]?.[machineInfo.demarcheTypeId]?.[etapeTypeId]?.[documentTypeIdSpecifique] if (isNotNullNorUndefined(documentSpecifique)) { const knownDocumentType = documentTypes.find(({ id }) => id === documentTypeIdSpecifique) @@ -395,9 +384,9 @@ export const getDocuments = ( }) if ( - machineId === 'ProcedureSpecifique' && - titreTypeId === TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX && - demarcheTypeId === DEMARCHES_TYPES_IDS.Octroi && + machineInfo.machineId === 'ProcedureSpecifique' && + machineInfo.titreTypeId === TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX && + machineInfo.demarcheTypeId === DEMARCHES_TYPES_IDS.Octroi && etapeTypeId === ETAPES_TYPES.demande ) { for (const documentType of documentTypes) { @@ -409,13 +398,13 @@ export const getDocuments = ( // si la démarche est mécanisée il faut ajouter des documents obligatoires if (isArmMecanise === IS_ARM_MECANISE) { for (const documentType of documentTypes) { - if ([DOCUMENTS_TYPES_IDS.dossierLoiSurLEau, machineId !== 'ProcedureSpecifique' ? DOCUMENTS_TYPES_IDS.decisionCasParCas : null].includes(documentType.id)) { + if ([DOCUMENTS_TYPES_IDS.dossierLoiSurLEau, machineInfo.machineId !== 'ProcedureSpecifique' ? DOCUMENTS_TYPES_IDS.decisionCasParCas : null].includes(documentType.id)) { documentType.optionnel = false } } } - const sdomZonesDocumentTypeIds = documentTypeIdsBySdomZonesGet(sdomZoneIds, titreTypeId, demarcheTypeId, etapeTypeId) + const sdomZonesDocumentTypeIds = documentTypeIdsBySdomZonesGet(sdomZoneIds, machineInfo.titreTypeId, machineInfo.demarcheTypeId, etapeTypeId) if (isNotNullNorUndefinedNorEmpty(sdomZonesDocumentTypeIds)) { for (const documentType of documentTypes) { if (sdomZonesDocumentTypeIds.includes(documentType.id)) { @@ -426,7 +415,7 @@ export const getDocuments = ( return [ ...documentTypes.map(d => { - if (isProcedureOuverte(machineId)) { + if (isProcedureOuverte(machineInfo.machineId)) { d.optionnel = true } diff --git a/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/entrepriseDocuments.test.ts b/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/entrepriseDocuments.test.ts index a4a4d2b3b..184e4b6ec 100644 --- a/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/entrepriseDocuments.test.ts +++ b/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/entrepriseDocuments.test.ts @@ -1,12 +1,26 @@ import { expect, test } from 'vitest' import { getEntrepriseDocuments } from './entrepriseDocuments' +import { TITRES_TYPES_IDS } from '../titresTypes' +import { DEMARCHES_TYPES_IDS } from '../demarchesTypes' +import { ETAPES_TYPES } from '../etapesTypes' +import { MachineInfo } from '../../machines' +import { demarcheIdValidator } from '../../demarche' +import { firstEtapeDateValidator } from '../../date' +const demarcheId = demarcheIdValidator.parse('demarcheId') +const firstEtapeDate = firstEtapeDateValidator.parse('2020-01-01') test('getEntrepriseDocuments pas de documents', () => { - expect(getEntrepriseDocuments('apm', 'amo', 'wfo')).toMatchInlineSnapshot('[]') + expect( + getEntrepriseDocuments( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_METAUX, DEMARCHES_TYPES_IDS.Amodiation, demarcheId, firstEtapeDate), + ETAPES_TYPES.declarationDouvertureDeTravauxMiniers_DOTM_ + ) + ).toMatchInlineSnapshot('[]') }) test('getEntrepriseDocuments', () => { - expect(getEntrepriseDocuments('arm', 'oct', 'mfr')).toMatchInlineSnapshot(` + expect(getEntrepriseDocuments(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), ETAPES_TYPES.demande)) + .toMatchInlineSnapshot(` [ { "description": undefined, @@ -58,7 +72,8 @@ test('getEntrepriseDocuments', () => { ] `) - expect(getEntrepriseDocuments('prr', 'oct', 'mfr')).toMatchInlineSnapshot(` + expect(getEntrepriseDocuments(MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_RADIOACTIF, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), ETAPES_TYPES.demande)) + .toMatchInlineSnapshot(` [ { "id": "atf", diff --git a/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/entrepriseDocuments.ts b/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/entrepriseDocuments.ts index 05bfd7a89..30f1d0935 100644 --- a/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/entrepriseDocuments.ts +++ b/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/entrepriseDocuments.ts @@ -1,3 +1,4 @@ +import { MachineInfo } from '../../machines' import { onlyUnique } from '../../typescript-tools' import { DEMARCHES_TYPES_IDS, DemarcheTypeId } from '../demarchesTypes' import { DocumentsTypes, DOCUMENTS_TYPES_IDS, EntrepriseDocumentTypeId, EntrepriseDocumentType, isEntrepriseDocumentTypeId } from '../documentsTypes' @@ -82,17 +83,19 @@ type TDEEntrepriseDocumentsTypesUnleashed = { [key in TitreTypeId]?: { [key in DemarcheTypeId]?: { [key in EtapeTypeId]?: { [key in EntrepriseDocumentTypeId]: { optionnel: boolean; description?: string } } } } } -export const getEntrepriseDocuments = (titreTypeId: TitreTypeId, demarcheTypeId: DemarcheTypeId, etapeTypeId: EtapeTypeId): EntrepriseDocumentType[] => { +export const getEntrepriseDocuments = (machineInfo: MachineInfo, etapeTypeId: EtapeTypeId): EntrepriseDocumentType[] => { const documentsIds: EntrepriseDocumentTypeId[] = [] if (isEtapesTypesEntrepriseDocumentsTypes(etapeTypeId)) { documentsIds.push(...EtapesTypesEntrepriseDocumentsTypes[etapeTypeId]) } - documentsIds.push(...Object.keys((TDEEntrepriseDocumentsTypes as TDEEntrepriseDocumentsTypesUnleashed)[titreTypeId]?.[demarcheTypeId]?.[etapeTypeId] ?? {}).filter(isEntrepriseDocumentTypeId)) + documentsIds.push( + ...Object.keys((TDEEntrepriseDocumentsTypes as TDEEntrepriseDocumentsTypesUnleashed)[machineInfo.titreTypeId]?.[machineInfo.demarcheTypeId]?.[etapeTypeId] ?? {}).filter(isEntrepriseDocumentTypeId) + ) return documentsIds.filter(onlyUnique).map(documentTypeId => { - const documentSpecifique = (TDEEntrepriseDocumentsTypes as TDEEntrepriseDocumentsTypesUnleashed)[titreTypeId]?.[demarcheTypeId]?.[etapeTypeId]?.[documentTypeId] + const documentSpecifique = (TDEEntrepriseDocumentsTypes as TDEEntrepriseDocumentsTypesUnleashed)[machineInfo.titreTypeId]?.[machineInfo.demarcheTypeId]?.[etapeTypeId]?.[documentTypeId] const document = { ...DocumentsTypes[documentTypeId], optionnel: true } if (documentSpecifique) { document.optionnel = documentSpecifique.optionnel diff --git a/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/sections.test.ts b/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/sections.test.ts index 50ae9e264..da2c54486 100644 --- a/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/sections.test.ts +++ b/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/sections.test.ts @@ -1,3 +1,6 @@ +import { firstEtapeDateValidator } from '../../date' +import { demarcheIdValidator } from '../../demarche' +import { MachineInfo } from '../../machines' import { isNumberElement } from '../../sections' import { DEMARCHES_TYPES_IDS } from '../demarchesTypes' import { ETAPES_TYPES } from '../etapesTypes' @@ -16,19 +19,31 @@ test('isNumberElement', () => { }) ).toBe(true) }) +const demarcheId = demarcheIdValidator.parse('demarcheId') +const firstEtapeDate = firstEtapeDateValidator.parse('2020-01-01') test('getSections erreurs', () => { - expect(() => getSections(undefined, undefined, undefined)).toThrowErrorMatchingInlineSnapshot( - "[Error: il manque des éléments pour trouver les sections titreTypeId: 'undefined', demarcheId: undefined, etapeTypeId: undefined]" - ) + expect(() => + getSections(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), undefined) + ).toThrowErrorMatchingInlineSnapshot(`[Error: il manque des éléments pour trouver les sections titreTypeId: 'arm', demarcheId: oct, etapeTypeId: undefined]`) }) test('getSections pas de surcharge mais pas de sections', () => { - expect(getSections(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_METAUX, DEMARCHES_TYPES_IDS.Amodiation, ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives)).toMatchInlineSnapshot('[]') + expect( + getSections( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_PROSPECTION_METAUX, DEMARCHES_TYPES_IDS.Amodiation, demarcheId, firstEtapeDate), + ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives + ) + ).toMatchInlineSnapshot('[]') }) test('getSections retourne le numéro de RAA pour les publications de décision au RAA', () => { - expect(getSections(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, ETAPES_TYPES.publicationDeDecisionAuRecueilDesActesAdministratifs)).toMatchInlineSnapshot(` + expect( + getSections( + MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), + ETAPES_TYPES.publicationDeDecisionAuRecueilDesActesAdministratifs + ) + ).toMatchInlineSnapshot(` [ { "elements": [ @@ -47,7 +62,8 @@ test('getSections retourne le numéro de RAA pour les publications de décision }) test('getSections surcharge', () => { - expect(getSections(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, ETAPES_TYPES.recepisseDeDeclarationLoiSurLeau)).toMatchInlineSnapshot(` + expect(getSections(MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), ETAPES_TYPES.recepisseDeDeclarationLoiSurLeau)) + .toMatchInlineSnapshot(` [ { "elements": [ diff --git a/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/sections.ts b/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/sections.ts index 6895ca3cf..be9f82938 100644 --- a/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/sections.ts +++ b/packages/common/src/static/titresTypes_demarchesTypes_etapesTypes/sections.ts @@ -10,6 +10,7 @@ import { z } from 'zod' import { ElementWithValue, SectionWithValue } from '../../sections' import { Contenu } from '../../permissions/sections' import { FlattenEtape } from '../../etape-form' +import { MachineInfo } from '../../machines' const sectionUnites = Object.values(Unites).map(({ id, nom }) => ({ id, nom })) as NonEmptyArray<{ id: UniteId; nom: string }> const sectionDevises = sortedDevises as NonEmptyArray<{ id: DeviseId; nom: string }> @@ -1016,13 +1017,13 @@ const isEtapesTypesEtapesTypesSections = (etapeTypeId?: EtapeTypeId): etapeTypeI return Object.keys(EtapesTypesSections).includes(etapeTypeId) } -export const getSections = (titreTypeId: TitreTypeId | undefined, demarcheTypeId: DemarcheTypeId | undefined, etapeTypeId: EtapeTypeId | undefined): Section[] => { - if (isNotNullNorUndefined(titreTypeId) && isNotNullNorUndefined(demarcheTypeId) && isNotNullNorUndefined(etapeTypeId)) { +export const getSections = (machineInfo: MachineInfo, etapeTypeId: EtapeTypeId | undefined): Section[] => { + if (isNotNullNorUndefined(machineInfo.titreTypeId) && isNotNullNorUndefined(machineInfo.demarcheTypeId) && isNotNullNorUndefined(etapeTypeId)) { const sections: Section[] = [] type TDESectionsTypesUnleashed = { [key in TitreTypeId]?: { [key in DemarcheTypeId]?: { [key in EtapeTypeId]?: Section[] } } } - sections.push(...((TDESections as TDESectionsTypesUnleashed)[titreTypeId]?.[demarcheTypeId]?.[etapeTypeId] ?? [])) + sections.push(...((TDESections as TDESectionsTypesUnleashed)[machineInfo.titreTypeId]?.[machineInfo.demarcheTypeId]?.[etapeTypeId] ?? [])) if (isEtapesTypesEtapesTypesSections(etapeTypeId)) { EtapesTypesSections[etapeTypeId].forEach(section => { @@ -1034,7 +1035,7 @@ export const getSections = (titreTypeId: TitreTypeId | undefined, demarcheTypeId return sections } else { - throw new Error(`il manque des éléments pour trouver les sections titreTypeId: '${titreTypeId}', demarcheId: ${demarcheTypeId}, etapeTypeId: ${etapeTypeId}`) + throw new Error(`il manque des éléments pour trouver les sections titreTypeId: '${machineInfo.titreTypeId}', demarcheId: ${machineInfo.demarcheTypeId}, etapeTypeId: ${etapeTypeId}`) } } diff --git a/packages/common/src/titres.ts b/packages/common/src/titres.ts index f2ae33c9e..a073b3005 100644 --- a/packages/common/src/titres.ts +++ b/packages/common/src/titres.ts @@ -14,6 +14,7 @@ import { EntrepriseId, entrepriseIdValidator } from './entreprise' import { isFondamentalesStatutOk } from './static/etapesStatuts' import { ETAPE_IS_NOT_BROUILLON, etapeIdValidator, etapeSlugValidator } from './etape' import { isEntrepriseOrBureauDEtude, User } from './roles' +import { machineIdValidator } from './validators/machine' const commonTitreValidator = z.object({ id: titreIdValidator, @@ -49,6 +50,7 @@ export const demarcheGetValidator = z.object({ demarche_date_debut: caminoDateValidator.nullable(), demarche_date_fin: caminoDateValidator.nullable(), demarche_visibilite: demarcheVisibiliteValidator, + machine_id: machineIdValidator.nullable(), ordre: z.number(), }) @@ -93,6 +95,7 @@ export const superTitreValidator = z.object({ etape_type_id: etapeTypeIdValidator, etape_slug: etapeSlugValidator, etape_date: caminoDateValidator, + machine_id: machineIdValidator.nullable(), }) export type SuperTitre = z.infer<typeof superTitreValidator> @@ -182,6 +185,7 @@ export const getDemarcheByIdOrSlugValidator = z.object({ demarche_slug: demarcheSlugValidator, demarche_type_id: demarcheTypeIdValidator, demarche_description: z.string().nullable(), + machine_id: machineIdValidator.nullable(), titre_id: titreIdValidator, titre_slug: titreSlugValidator, titre_type_id: titreTypeIdValidator, diff --git a/packages/common/src/validators/machine.ts b/packages/common/src/validators/machine.ts new file mode 100644 index 000000000..42df508d1 --- /dev/null +++ b/packages/common/src/validators/machine.ts @@ -0,0 +1,13 @@ +import { z } from 'zod' +const CAMINO_MACHINES = [ + 'AncienLogigrammeOctroiARM', + 'AncienLogigrammeRenonciationEtProlongationARM', + 'AncienLogigrammeOctroiPRM', + 'AncienLogigrammeOctroiAXM', + 'AncienLogigrammeProlongationAXM', + 'ProcedureSimplifiee', + 'ProcedureSpecifique', +] as const +export const machineIdValidator = z.enum(CAMINO_MACHINES) + +export type CaminoMachineId = (typeof CAMINO_MACHINES)[number] diff --git a/packages/ui/src/components/_common/dsfr-perimetre.stories.tsx b/packages/ui/src/components/_common/dsfr-perimetre.stories.tsx index 642bad974..fe18ee537 100644 --- a/packages/ui/src/components/_common/dsfr-perimetre.stories.tsx +++ b/packages/ui/src/components/_common/dsfr-perimetre.stories.tsx @@ -9,6 +9,10 @@ import { FeatureCollectionForages, FeatureCollectionPoints, FeatureMultiPolygon import { ApiClient } from '@/api/api-client' import { GEO_SYSTEME_IDS } from 'camino-common/src/static/geoSystemes' import { km2Validator } from 'camino-common/src/number' +import { MachineInfo } from 'camino-common/src/machines' +import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes' +import { demarcheIdValidator } from 'camino-common/src/demarche' +import { firstEtapeDateValidator } from 'camino-common/src/date' const meta: Meta = { title: 'Components/Common/Perimetre', @@ -54,13 +58,18 @@ const apiClientMock: Pick<ApiClient, 'getTitresWithPerimetreForCarte'> = { return Promise.resolve({ elements: [], total: 0 }) }, } - +const machineInfo = MachineInfo.withDate( + TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX, + DEMARCHES_TYPES_IDS.Octroi, + demarcheIdValidator.parse('demarcheId'), + firstEtapeDateValidator.parse('2020-01-01') +) export const Default: StoryFn = () => ( <> <MapPattern /> <DsfrPerimetre id="test" - titreTypeId="axm" + machineInfo={machineInfo} perimetre={{ geojson4326_perimetre, geojson4326_points: null, @@ -128,7 +137,7 @@ export const NoNeighbors: StoryFn = () => ( <MapPattern /> <DsfrPerimetre id="test" - titreTypeId="axm" + machineInfo={machineInfo} perimetre={{ geojson4326_perimetre, geojson4326_points: null, @@ -174,7 +183,7 @@ export const PolygonWithLacune: StoryFn = () => ( <MapPattern /> <DsfrPerimetre id="test" - titreTypeId="axm" + machineInfo={machineInfo} perimetre={{ geojson4326_perimetre: perimetreWithLacune, geojson4326_points: null, @@ -217,7 +226,7 @@ export const Big: StoryFn = () => ( <MapPattern /> <DsfrPerimetre id="test" - titreTypeId="axm" + machineInfo={machineInfo} perimetre={{ geojson4326_perimetre: bigGeoJson, geojson4326_points: null, @@ -284,7 +293,7 @@ export const Multiple: StoryFn = () => ( <MapPattern /> <DsfrPerimetre id="test" - titreTypeId="axm" + machineInfo={machineInfo} perimetre={{ geojson4326_perimetre: multiplePolygone, geojson_origine_perimetre: multiplePolygone, @@ -373,7 +382,7 @@ export const MultiplePolygonWithLacuneTableau: StoryFn = () => ( <MapPattern /> <DsfrPerimetre id="test" - titreTypeId="axm" + machineInfo={machineInfo} perimetre={{ geojson4326_perimetre: multiplePolygoneWithLacune, geojson4326_points: null, @@ -411,7 +420,7 @@ export const CustomPoints: StoryFn = () => ( <MapPattern /> <DsfrPerimetre id="test" - titreTypeId="axm" + machineInfo={machineInfo} perimetre={{ geojson4326_perimetre, geojson4326_points: customPoints, @@ -439,7 +448,7 @@ export const CustomPointsWithoutNameAndDesc: StoryFn = () => ( <MapPattern /> <DsfrPerimetre id="test" - titreTypeId="axm" + machineInfo={machineInfo} perimetre={{ geojson4326_perimetre, geojson4326_points: customPointWithoutNameAndDesc, @@ -462,7 +471,7 @@ export const CustomPointsWithAnotherGeoSysteme: StoryFn = () => ( <MapPattern /> <DsfrPerimetre id="test" - titreTypeId="axm" + machineInfo={machineInfo} perimetre={{ geojson4326_perimetre, geojson4326_points: customPointWithoutNameAndDesc, @@ -489,7 +498,7 @@ export const CustomPointsWithAnotherLegacyGeoSysteme: StoryFn = () => ( <MapPattern /> <DsfrPerimetre id="test" - titreTypeId="axm" + machineInfo={machineInfo} perimetre={{ geojson4326_perimetre, geojson4326_points: customPointWithoutNameAndDesc, @@ -514,7 +523,7 @@ export const CustomPointsWithAnotherLegacyGeoSysteme: StoryFn = () => ( export const WithForages: StoryFn = () => ( <DsfrPerimetre id="test" - titreTypeId="pxm" + machineInfo={MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheIdValidator.parse('demarcheId'), firstEtapeDateValidator.parse('2020-01-01'))} perimetre={{ geojson4326_perimetre, geojson4326_points: customPointWithoutNameAndDesc, diff --git a/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_Big.html b/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_Big.html index dd1755f3d..7d84c157a 100644 --- a/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_Big.html +++ b/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_Big.html @@ -305,10 +305,10 @@ </ul> <div id="tabpanel-carte-test-panel" class="fr-tabs__panel fr-tabs__panel--selected" role="tabpanel" aria-labelledby="tabpanel-carte-test" tabindex="0"> <div style="display: flex; flex-direction: column;"> - <mocked-map perimetre="[object Object]" id="test" titretypeid="axm" style="min-height: 400px;" class="fr-mb-1w" maxmarkers="20" neighbours="[object Object]"> + <mocked-map perimetre="[object Object]" id="test" machineinfo="[object Object]" style="min-height: 400px;" class="fr-mb-1w" maxmarkers="20" neighbours="[object Object]"> <perimetre>{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-4.370364497124209,48.53380508608616],[-4.373271574712479,48.47151134163559],[-4.03753485335386,48.579164636474836],[-3.89919702975027,48.603980178934115],[-3.860482328708233,48.62511389817695],[-3.858436311611334,48.629031691751045],[-3.862157259991486,48.633014015139416],[-3.870281882041237,48.63550010399696],[-3.879786359001045,48.639113643702565],[-3.895430188480503,48.64455770816115],[-3.89902273351368,48.64822789311303],[-3.902536979616769,48.654435032933826],[-3.906528075174153,48.66061643462235],[-3.904489574558275,48.6643307169305],[-3.89647573803132,48.66601900245078],[-3.890673665115296,48.667020244464325],[-3.890721315690864,48.67062455977177],[-3.892950905315848,48.67088770685571],[-3.898005277721187,48.6723935639094],[-3.8992413951649,48.67074624589731],[-3.903300809713803,48.67034264689684],[-3.907548440632195,48.66910635173531],[-3.91185396569359,48.669954398127075],[-3.914635548862354,48.67322568941628],[-3.920575104032537,48.67458696237509],[-3.924157593611878,48.669749821082725],[-3.927138109422188,48.66538094626539],[-3.927802453245391,48.66178827244388],[-3.92880004801291,48.660065331624466],[-3.930674658925236,48.657424523021],[-3.934385020441046,48.65730036039394],[-3.940574301992641,48.65682750256307],[-3.949892212356874,48.653210569309856],[-3.9518951695476,48.64983646195122],[-3.95135848409069,48.646306571150944],[-3.952791103114349,48.64456097348628],[-3.954311041643234,48.64535110107629],[-3.957178207067545,48.65093506946735],[-3.95632686509049,48.654756209794456],[-3.954939197043658,48.66049485799891],[-3.958264581105623,48.66351217516115],[-3.954301077151103,48.665175330569724],[-3.958113788215813,48.66678821578858],[-3.958288500972019,48.67004622329816],[-3.953583216471425,48.67102223996598],[-3.952154912225681,48.67280542236],[-3.954601922703807,48.67354649576719],[-3.957150323952388,48.6728667311387],[-3.962232217223142,48.674085603023535],[-3.96509885038279,48.67647290565392],[-3.968196892552599,48.67354977814375],[-3.970552500285286,48.67336152037275],[-3.971907150463719,48.67429537178488],[-3.971687730880199,48.67565139942766],[-3.968925351937541,48.67998621214178],[-3.97276835094199,48.68681279071675],[-3.969905040239144,48.687617856017994],[-3.967785856011854,48.69274164929216],[-3.97050395358365,48.693904041872074],[-3.974129066864182,48.69665141578885],[-3.976827175680581,48.699084231748806],[-3.973964059500176,48.70207052891004],[-3.97557715354335,48.70449012698265],[-3.972337757698344,48.70582333762662],[-3.974038535718974,48.710344199247295],[-3.972061362590358,48.71168433267898],[-3.969407494937729,48.71919463600953],[-3.966114995158957,48.719188628020184],[-3.964815895310649,48.72248973384656],[-3.968123622922862,48.72216808659624],[-3.970117554054281,48.7239825094888],[-3.971030085004171,48.72531725688056],[-3.974105493634571,48.72442714535237],[-3.977130032296356,48.72223266964199],[-3.98038470744471,48.72282149601802],[-3.98267568678471,48.72451484026706],[-3.983159793997456,48.72623219482621],[-3.985655519886893,48.726898196761965],[-3.988412331317411,48.727004809776105],[-3.990251104366354,48.72588975599552],[-3.992106999472123,48.723541171653366],[-3.992308257471176,48.72204072794657],[-3.990818477440011,48.71838055340067],[-3.993241558794496,48.715311146944074],[-3.99726181945054,48.71273584775902],[-4.000886986292233,48.71141716999743],[-4.005573266114372,48.715195490443925],[-4.004640753163968,48.716989015759715],[-4.007861713401779,48.72044675798358],[-4.009590286562232,48.72068101995395],[-4.012907971574204,48.71865165832863],[-4.010881803078078,48.716872551149415],[-4.013298574720932,48.713765123429766],[-4.018283788022766,48.71146515516518],[-4.02502266800395,48.710486602386844],[-4.029102910364339,48.7109751516783],[-4.032895375568785,48.712496949149184],[-4.034013864663466,48.71364906002572],[-4.035203599079426,48.71386049099469],[-4.036426674181452,48.711761570746404],[-4.035857818689737,48.70935978588029],[-4.037836186006247,48.70536884991981],[-4.040876440962449,48.70331706201061],[-4.042661395770205,48.70267658451317],[-4.044522857875245,48.70264835316387],[-4.048746772595955,48.70536952092104],[-4.051782617787177,48.70458102418029],[-4.053387641319855,48.70237110662314],[-4.054960885021424,48.69887510664347],[-4.057098904957046,48.688336149296134],[-4.047492224129947,48.6881905546806],[-4.04264615919883,48.688356681641565],[-4.05570877851515,48.685187990084636],[-4.061384711067841,48.687678086132514],[-4.063856568443375,48.68626486757381],[-4.069006699782528,48.687977416990556],[-4.066114156101222,48.68600063748565],[-4.065917761777147,48.68383188367652],[-4.06536435070835,48.68281963355705],[-4.062811851052143,48.68243638561189],[-4.063604286352126,48.680735563101265],[-4.061249339782617,48.68019915458731],[-4.060491984152113,48.67893668983929],[-4.056630622211962,48.67523642323898],[-4.055350396131191,48.67179995101334],[-4.057224936686009,48.670572879663034],[-4.057969445321888,48.675068847630506],[-4.059622862128396,48.675122344607715],[-4.06024682153259,48.67613145254186],[-4.063213863275964,48.67815002912692],[-4.064507934140134,48.677605925445725],[-4.067195178609656,48.67891661518815],[-4.068000601946539,48.68272446881325],[-4.07116708376152,48.68462241191764],[-4.080222240659125,48.689712089777736],[-4.082890717412141,48.693212237422216],[-4.0837341887691,48.69168549285934],[-4.08645810312384,48.69005696722575],[-4.08922980276701,48.69161527586137],[-4.091651149022687,48.69171173600047],[-4.095188717132302,48.686965610139666],[-4.097383839952319,48.69356464812578],[-4.102536986221444,48.69351221259058],[-4.106197887484285,48.692515838515405],[-4.109568285925066,48.69472448012849],[-4.115803404112282,48.69506791354793],[-4.118098969264236,48.692778728280935],[-4.12511664716867,48.693877169595176],[-4.127837461875522,48.69361476668908],[-4.131236501370729,48.6960475956426],[-4.136181126707938,48.69293107079426],[-4.142132619722753,48.69237814384752],[-4.150020162763907,48.69217377284019],[-4.152170300893284,48.691487051119246],[-4.162483098525137,48.68833023827453],[-4.174170898732186,48.657628672506775],[-4.409843663429304,48.633874515395604],[-4.370364497124209,48.53380508608616]]]]}},"geojson4326_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.370364497124209,48.53380508608616]},"properties":{"nom":"A","description":"Polygone 1","latitude":"48.53380508608616","longitude":"-4.370364497124209"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.373271574712479,48.47151134163559]},"properties":{"nom":"B","description":"Polygone 1","latitude":"48.47151134163559","longitude":"-4.373271574712479"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.03753485335386,48.579164636474836]},"properties":{"nom":"C","description":"Polygone 1","latitude":"48.579164636474836","longitude":"-4.03753485335386"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.89919702975027,48.603980178934115]},"properties":{"nom":"D","description":"Polygone 1","latitude":"48.603980178934115","longitude":"-3.89919702975027"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.860482328708233,48.62511389817695]},"properties":{"nom":"E","description":"Polygone 1","latitude":"48.62511389817695","longitude":"-3.860482328708233"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.858436311611334,48.629031691751045]},"properties":{"nom":"F","description":"Polygone 1","latitude":"48.629031691751045","longitude":"-3.858436311611334"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.862157259991486,48.633014015139416]},"properties":{"nom":"G","description":"Polygone 1","latitude":"48.633014015139416","longitude":"-3.862157259991486"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.870281882041237,48.63550010399696]},"properties":{"nom":"H","description":"Polygone 1","latitude":"48.63550010399696","longitude":"-3.870281882041237"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.879786359001045,48.639113643702565]},"properties":{"nom":"I","description":"Polygone 1","latitude":"48.639113643702565","longitude":"-3.879786359001045"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.895430188480503,48.64455770816115]},"properties":{"nom":"J","description":"Polygone 1","latitude":"48.64455770816115","longitude":"-3.895430188480503"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.89902273351368,48.64822789311303]},"properties":{"nom":"K","description":"Polygone 1","latitude":"48.64822789311303","longitude":"-3.89902273351368"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.902536979616769,48.654435032933826]},"properties":{"nom":"L","description":"Polygone 1","latitude":"48.654435032933826","longitude":"-3.902536979616769"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.906528075174153,48.66061643462235]},"properties":{"nom":"M","description":"Polygone 1","latitude":"48.66061643462235","longitude":"-3.906528075174153"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.904489574558275,48.6643307169305]},"properties":{"nom":"N","description":"Polygone 1","latitude":"48.6643307169305","longitude":"-3.904489574558275"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.89647573803132,48.66601900245078]},"properties":{"nom":"O","description":"Polygone 1","latitude":"48.66601900245078","longitude":"-3.89647573803132"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.890673665115296,48.667020244464325]},"properties":{"nom":"P","description":"Polygone 1","latitude":"48.667020244464325","longitude":"-3.890673665115296"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.890721315690864,48.67062455977177]},"properties":{"nom":"Q","description":"Polygone 1","latitude":"48.67062455977177","longitude":"-3.890721315690864"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.892950905315848,48.67088770685571]},"properties":{"nom":"R","description":"Polygone 1","latitude":"48.67088770685571","longitude":"-3.892950905315848"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.898005277721187,48.6723935639094]},"properties":{"nom":"S","description":"Polygone 1","latitude":"48.6723935639094","longitude":"-3.898005277721187"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.8992413951649,48.67074624589731]},"properties":{"nom":"T","description":"Polygone 1","latitude":"48.67074624589731","longitude":"-3.8992413951649"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.903300809713803,48.67034264689684]},"properties":{"nom":"U","description":"Polygone 1","latitude":"48.67034264689684","longitude":"-3.903300809713803"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.907548440632195,48.66910635173531]},"properties":{"nom":"V","description":"Polygone 1","latitude":"48.66910635173531","longitude":"-3.907548440632195"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.91185396569359,48.669954398127075]},"properties":{"nom":"W","description":"Polygone 1","latitude":"48.669954398127075","longitude":"-3.91185396569359"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.914635548862354,48.67322568941628]},"properties":{"nom":"X","description":"Polygone 1","latitude":"48.67322568941628","longitude":"-3.914635548862354"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.920575104032537,48.67458696237509]},"properties":{"nom":"Y","description":"Polygone 1","latitude":"48.67458696237509","longitude":"-3.920575104032537"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.924157593611878,48.669749821082725]},"properties":{"nom":"Z","description":"Polygone 1","latitude":"48.669749821082725","longitude":"-3.924157593611878"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.927138109422188,48.66538094626539]},"properties":{"nom":"AA","description":"Polygone 1","latitude":"48.66538094626539","longitude":"-3.927138109422188"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.927802453245391,48.66178827244388]},"properties":{"nom":"AB","description":"Polygone 1","latitude":"48.66178827244388","longitude":"-3.927802453245391"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.92880004801291,48.660065331624466]},"properties":{"nom":"AC","description":"Polygone 1","latitude":"48.660065331624466","longitude":"-3.92880004801291"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.930674658925236,48.657424523021]},"properties":{"nom":"AD","description":"Polygone 1","latitude":"48.657424523021","longitude":"-3.930674658925236"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.934385020441046,48.65730036039394]},"properties":{"nom":"AE","description":"Polygone 1","latitude":"48.65730036039394","longitude":"-3.934385020441046"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.940574301992641,48.65682750256307]},"properties":{"nom":"AF","description":"Polygone 1","latitude":"48.65682750256307","longitude":"-3.940574301992641"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.949892212356874,48.653210569309856]},"properties":{"nom":"AG","description":"Polygone 1","latitude":"48.653210569309856","longitude":"-3.949892212356874"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.9518951695476,48.64983646195122]},"properties":{"nom":"AH","description":"Polygone 1","latitude":"48.64983646195122","longitude":"-3.9518951695476"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.95135848409069,48.646306571150944]},"properties":{"nom":"AI","description":"Polygone 1","latitude":"48.646306571150944","longitude":"-3.95135848409069"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.952791103114349,48.64456097348628]},"properties":{"nom":"AJ","description":"Polygone 1","latitude":"48.64456097348628","longitude":"-3.952791103114349"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.954311041643234,48.64535110107629]},"properties":{"nom":"AK","description":"Polygone 1","latitude":"48.64535110107629","longitude":"-3.954311041643234"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.957178207067545,48.65093506946735]},"properties":{"nom":"AL","description":"Polygone 1","latitude":"48.65093506946735","longitude":"-3.957178207067545"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.95632686509049,48.654756209794456]},"properties":{"nom":"AM","description":"Polygone 1","latitude":"48.654756209794456","longitude":"-3.95632686509049"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.954939197043658,48.66049485799891]},"properties":{"nom":"AN","description":"Polygone 1","latitude":"48.66049485799891","longitude":"-3.954939197043658"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.958264581105623,48.66351217516115]},"properties":{"nom":"AO","description":"Polygone 1","latitude":"48.66351217516115","longitude":"-3.958264581105623"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.954301077151103,48.665175330569724]},"properties":{"nom":"AP","description":"Polygone 1","latitude":"48.665175330569724","longitude":"-3.954301077151103"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.958113788215813,48.66678821578858]},"properties":{"nom":"AQ","description":"Polygone 1","latitude":"48.66678821578858","longitude":"-3.958113788215813"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.958288500972019,48.67004622329816]},"properties":{"nom":"AR","description":"Polygone 1","latitude":"48.67004622329816","longitude":"-3.958288500972019"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.953583216471425,48.67102223996598]},"properties":{"nom":"AS","description":"Polygone 1","latitude":"48.67102223996598","longitude":"-3.953583216471425"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.952154912225681,48.67280542236]},"properties":{"nom":"AT","description":"Polygone 1","latitude":"48.67280542236","longitude":"-3.952154912225681"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.954601922703807,48.67354649576719]},"properties":{"nom":"AU","description":"Polygone 1","latitude":"48.67354649576719","longitude":"-3.954601922703807"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.957150323952388,48.6728667311387]},"properties":{"nom":"AV","description":"Polygone 1","latitude":"48.6728667311387","longitude":"-3.957150323952388"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.962232217223142,48.674085603023535]},"properties":{"nom":"AW","description":"Polygone 1","latitude":"48.674085603023535","longitude":"-3.962232217223142"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.96509885038279,48.67647290565392]},"properties":{"nom":"AX","description":"Polygone 1","latitude":"48.67647290565392","longitude":"-3.96509885038279"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.968196892552599,48.67354977814375]},"properties":{"nom":"AY","description":"Polygone 1","latitude":"48.67354977814375","longitude":"-3.968196892552599"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.970552500285286,48.67336152037275]},"properties":{"nom":"AZ","description":"Polygone 1","latitude":"48.67336152037275","longitude":"-3.970552500285286"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.971907150463719,48.67429537178488]},"properties":{"nom":"BA","description":"Polygone 1","latitude":"48.67429537178488","longitude":"-3.971907150463719"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.971687730880199,48.67565139942766]},"properties":{"nom":"BB","description":"Polygone 1","latitude":"48.67565139942766","longitude":"-3.971687730880199"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.968925351937541,48.67998621214178]},"properties":{"nom":"BC","description":"Polygone 1","latitude":"48.67998621214178","longitude":"-3.968925351937541"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.97276835094199,48.68681279071675]},"properties":{"nom":"BD","description":"Polygone 1","latitude":"48.68681279071675","longitude":"-3.97276835094199"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.969905040239144,48.687617856017994]},"properties":{"nom":"BE","description":"Polygone 1","latitude":"48.687617856017994","longitude":"-3.969905040239144"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.967785856011854,48.69274164929216]},"properties":{"nom":"BF","description":"Polygone 1","latitude":"48.69274164929216","longitude":"-3.967785856011854"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.97050395358365,48.693904041872074]},"properties":{"nom":"BG","description":"Polygone 1","latitude":"48.693904041872074","longitude":"-3.97050395358365"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.974129066864182,48.69665141578885]},"properties":{"nom":"BH","description":"Polygone 1","latitude":"48.69665141578885","longitude":"-3.974129066864182"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.976827175680581,48.699084231748806]},"properties":{"nom":"BI","description":"Polygone 1","latitude":"48.699084231748806","longitude":"-3.976827175680581"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.973964059500176,48.70207052891004]},"properties":{"nom":"BJ","description":"Polygone 1","latitude":"48.70207052891004","longitude":"-3.973964059500176"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.97557715354335,48.70449012698265]},"properties":{"nom":"BK","description":"Polygone 1","latitude":"48.70449012698265","longitude":"-3.97557715354335"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.972337757698344,48.70582333762662]},"properties":{"nom":"BL","description":"Polygone 1","latitude":"48.70582333762662","longitude":"-3.972337757698344"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.974038535718974,48.710344199247295]},"properties":{"nom":"BM","description":"Polygone 1","latitude":"48.710344199247295","longitude":"-3.974038535718974"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.972061362590358,48.71168433267898]},"properties":{"nom":"BN","description":"Polygone 1","latitude":"48.71168433267898","longitude":"-3.972061362590358"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.969407494937729,48.71919463600953]},"properties":{"nom":"BO","description":"Polygone 1","latitude":"48.71919463600953","longitude":"-3.969407494937729"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.966114995158957,48.719188628020184]},"properties":{"nom":"BP","description":"Polygone 1","latitude":"48.719188628020184","longitude":"-3.966114995158957"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.964815895310649,48.72248973384656]},"properties":{"nom":"BQ","description":"Polygone 1","latitude":"48.72248973384656","longitude":"-3.964815895310649"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.968123622922862,48.72216808659624]},"properties":{"nom":"BR","description":"Polygone 1","latitude":"48.72216808659624","longitude":"-3.968123622922862"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.970117554054281,48.7239825094888]},"properties":{"nom":"BS","description":"Polygone 1","latitude":"48.7239825094888","longitude":"-3.970117554054281"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.971030085004171,48.72531725688056]},"properties":{"nom":"BT","description":"Polygone 1","latitude":"48.72531725688056","longitude":"-3.971030085004171"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.974105493634571,48.72442714535237]},"properties":{"nom":"BU","description":"Polygone 1","latitude":"48.72442714535237","longitude":"-3.974105493634571"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.977130032296356,48.72223266964199]},"properties":{"nom":"BV","description":"Polygone 1","latitude":"48.72223266964199","longitude":"-3.977130032296356"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.98038470744471,48.72282149601802]},"properties":{"nom":"BW","description":"Polygone 1","latitude":"48.72282149601802","longitude":"-3.98038470744471"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.98267568678471,48.72451484026706]},"properties":{"nom":"BX","description":"Polygone 1","latitude":"48.72451484026706","longitude":"-3.98267568678471"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.983159793997456,48.72623219482621]},"properties":{"nom":"BY","description":"Polygone 1","latitude":"48.72623219482621","longitude":"-3.983159793997456"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.985655519886893,48.726898196761965]},"properties":{"nom":"BZ","description":"Polygone 1","latitude":"48.726898196761965","longitude":"-3.985655519886893"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.988412331317411,48.727004809776105]},"properties":{"nom":"CA","description":"Polygone 1","latitude":"48.727004809776105","longitude":"-3.988412331317411"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.990251104366354,48.72588975599552]},"properties":{"nom":"CB","description":"Polygone 1","latitude":"48.72588975599552","longitude":"-3.990251104366354"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.992106999472123,48.723541171653366]},"properties":{"nom":"CC","description":"Polygone 1","latitude":"48.723541171653366","longitude":"-3.992106999472123"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.992308257471176,48.72204072794657]},"properties":{"nom":"CD","description":"Polygone 1","latitude":"48.72204072794657","longitude":"-3.992308257471176"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.990818477440011,48.71838055340067]},"properties":{"nom":"CE","description":"Polygone 1","latitude":"48.71838055340067","longitude":"-3.990818477440011"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.993241558794496,48.715311146944074]},"properties":{"nom":"CF","description":"Polygone 1","latitude":"48.715311146944074","longitude":"-3.993241558794496"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.99726181945054,48.71273584775902]},"properties":{"nom":"CG","description":"Polygone 1","latitude":"48.71273584775902","longitude":"-3.99726181945054"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.000886986292233,48.71141716999743]},"properties":{"nom":"CH","description":"Polygone 1","latitude":"48.71141716999743","longitude":"-4.000886986292233"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.005573266114372,48.715195490443925]},"properties":{"nom":"CI","description":"Polygone 1","latitude":"48.715195490443925","longitude":"-4.005573266114372"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.004640753163968,48.716989015759715]},"properties":{"nom":"CJ","description":"Polygone 1","latitude":"48.716989015759715","longitude":"-4.004640753163968"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.007861713401779,48.72044675798358]},"properties":{"nom":"CK","description":"Polygone 1","latitude":"48.72044675798358","longitude":"-4.007861713401779"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.009590286562232,48.72068101995395]},"properties":{"nom":"CL","description":"Polygone 1","latitude":"48.72068101995395","longitude":"-4.009590286562232"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.012907971574204,48.71865165832863]},"properties":{"nom":"CM","description":"Polygone 1","latitude":"48.71865165832863","longitude":"-4.012907971574204"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.010881803078078,48.716872551149415]},"properties":{"nom":"CN","description":"Polygone 1","latitude":"48.716872551149415","longitude":"-4.010881803078078"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.013298574720932,48.713765123429766]},"properties":{"nom":"CO","description":"Polygone 1","latitude":"48.713765123429766","longitude":"-4.013298574720932"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.018283788022766,48.71146515516518]},"properties":{"nom":"CP","description":"Polygone 1","latitude":"48.71146515516518","longitude":"-4.018283788022766"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.02502266800395,48.710486602386844]},"properties":{"nom":"CQ","description":"Polygone 1","latitude":"48.710486602386844","longitude":"-4.02502266800395"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.029102910364339,48.7109751516783]},"properties":{"nom":"CR","description":"Polygone 1","latitude":"48.7109751516783","longitude":"-4.029102910364339"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.032895375568785,48.712496949149184]},"properties":{"nom":"CS","description":"Polygone 1","latitude":"48.712496949149184","longitude":"-4.032895375568785"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.034013864663466,48.71364906002572]},"properties":{"nom":"CT","description":"Polygone 1","latitude":"48.71364906002572","longitude":"-4.034013864663466"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.035203599079426,48.71386049099469]},"properties":{"nom":"CU","description":"Polygone 1","latitude":"48.71386049099469","longitude":"-4.035203599079426"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.036426674181452,48.711761570746404]},"properties":{"nom":"CV","description":"Polygone 1","latitude":"48.711761570746404","longitude":"-4.036426674181452"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.035857818689737,48.70935978588029]},"properties":{"nom":"CW","description":"Polygone 1","latitude":"48.70935978588029","longitude":"-4.035857818689737"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.037836186006247,48.70536884991981]},"properties":{"nom":"CX","description":"Polygone 1","latitude":"48.70536884991981","longitude":"-4.037836186006247"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.040876440962449,48.70331706201061]},"properties":{"nom":"CY","description":"Polygone 1","latitude":"48.70331706201061","longitude":"-4.040876440962449"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.042661395770205,48.70267658451317]},"properties":{"nom":"CZ","description":"Polygone 1","latitude":"48.70267658451317","longitude":"-4.042661395770205"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.044522857875245,48.70264835316387]},"properties":{"nom":"DA","description":"Polygone 1","latitude":"48.70264835316387","longitude":"-4.044522857875245"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.048746772595955,48.70536952092104]},"properties":{"nom":"DB","description":"Polygone 1","latitude":"48.70536952092104","longitude":"-4.048746772595955"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.051782617787177,48.70458102418029]},"properties":{"nom":"DC","description":"Polygone 1","latitude":"48.70458102418029","longitude":"-4.051782617787177"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.053387641319855,48.70237110662314]},"properties":{"nom":"DD","description":"Polygone 1","latitude":"48.70237110662314","longitude":"-4.053387641319855"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.054960885021424,48.69887510664347]},"properties":{"nom":"DE","description":"Polygone 1","latitude":"48.69887510664347","longitude":"-4.054960885021424"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.057098904957046,48.688336149296134]},"properties":{"nom":"DF","description":"Polygone 1","latitude":"48.688336149296134","longitude":"-4.057098904957046"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.047492224129947,48.6881905546806]},"properties":{"nom":"DG","description":"Polygone 1","latitude":"48.6881905546806","longitude":"-4.047492224129947"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.04264615919883,48.688356681641565]},"properties":{"nom":"DH","description":"Polygone 1","latitude":"48.688356681641565","longitude":"-4.04264615919883"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.05570877851515,48.685187990084636]},"properties":{"nom":"DI","description":"Polygone 1","latitude":"48.685187990084636","longitude":"-4.05570877851515"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.061384711067841,48.687678086132514]},"properties":{"nom":"DJ","description":"Polygone 1","latitude":"48.687678086132514","longitude":"-4.061384711067841"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.063856568443375,48.68626486757381]},"properties":{"nom":"DK","description":"Polygone 1","latitude":"48.68626486757381","longitude":"-4.063856568443375"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.069006699782528,48.687977416990556]},"properties":{"nom":"DL","description":"Polygone 1","latitude":"48.687977416990556","longitude":"-4.069006699782528"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.066114156101222,48.68600063748565]},"properties":{"nom":"DM","description":"Polygone 1","latitude":"48.68600063748565","longitude":"-4.066114156101222"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.065917761777147,48.68383188367652]},"properties":{"nom":"DN","description":"Polygone 1","latitude":"48.68383188367652","longitude":"-4.065917761777147"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.06536435070835,48.68281963355705]},"properties":{"nom":"DO","description":"Polygone 1","latitude":"48.68281963355705","longitude":"-4.06536435070835"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.062811851052143,48.68243638561189]},"properties":{"nom":"DP","description":"Polygone 1","latitude":"48.68243638561189","longitude":"-4.062811851052143"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.063604286352126,48.680735563101265]},"properties":{"nom":"DQ","description":"Polygone 1","latitude":"48.680735563101265","longitude":"-4.063604286352126"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.061249339782617,48.68019915458731]},"properties":{"nom":"DR","description":"Polygone 1","latitude":"48.68019915458731","longitude":"-4.061249339782617"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.060491984152113,48.67893668983929]},"properties":{"nom":"DS","description":"Polygone 1","latitude":"48.67893668983929","longitude":"-4.060491984152113"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.056630622211962,48.67523642323898]},"properties":{"nom":"DT","description":"Polygone 1","latitude":"48.67523642323898","longitude":"-4.056630622211962"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.055350396131191,48.67179995101334]},"properties":{"nom":"DU","description":"Polygone 1","latitude":"48.67179995101334","longitude":"-4.055350396131191"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.057224936686009,48.670572879663034]},"properties":{"nom":"DV","description":"Polygone 1","latitude":"48.670572879663034","longitude":"-4.057224936686009"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.057969445321888,48.675068847630506]},"properties":{"nom":"DW","description":"Polygone 1","latitude":"48.675068847630506","longitude":"-4.057969445321888"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.059622862128396,48.675122344607715]},"properties":{"nom":"DX","description":"Polygone 1","latitude":"48.675122344607715","longitude":"-4.059622862128396"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.06024682153259,48.67613145254186]},"properties":{"nom":"DY","description":"Polygone 1","latitude":"48.67613145254186","longitude":"-4.06024682153259"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.063213863275964,48.67815002912692]},"properties":{"nom":"DZ","description":"Polygone 1","latitude":"48.67815002912692","longitude":"-4.063213863275964"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.064507934140134,48.677605925445725]},"properties":{"nom":"EA","description":"Polygone 1","latitude":"48.677605925445725","longitude":"-4.064507934140134"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.067195178609656,48.67891661518815]},"properties":{"nom":"EB","description":"Polygone 1","latitude":"48.67891661518815","longitude":"-4.067195178609656"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.068000601946539,48.68272446881325]},"properties":{"nom":"EC","description":"Polygone 1","latitude":"48.68272446881325","longitude":"-4.068000601946539"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.07116708376152,48.68462241191764]},"properties":{"nom":"ED","description":"Polygone 1","latitude":"48.68462241191764","longitude":"-4.07116708376152"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.080222240659125,48.689712089777736]},"properties":{"nom":"EE","description":"Polygone 1","latitude":"48.689712089777736","longitude":"-4.080222240659125"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.082890717412141,48.693212237422216]},"properties":{"nom":"EF","description":"Polygone 1","latitude":"48.693212237422216","longitude":"-4.082890717412141"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.0837341887691,48.69168549285934]},"properties":{"nom":"EG","description":"Polygone 1","latitude":"48.69168549285934","longitude":"-4.0837341887691"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.08645810312384,48.69005696722575]},"properties":{"nom":"EH","description":"Polygone 1","latitude":"48.69005696722575","longitude":"-4.08645810312384"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.08922980276701,48.69161527586137]},"properties":{"nom":"EI","description":"Polygone 1","latitude":"48.69161527586137","longitude":"-4.08922980276701"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.091651149022687,48.69171173600047]},"properties":{"nom":"EJ","description":"Polygone 1","latitude":"48.69171173600047","longitude":"-4.091651149022687"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.095188717132302,48.686965610139666]},"properties":{"nom":"EK","description":"Polygone 1","latitude":"48.686965610139666","longitude":"-4.095188717132302"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.097383839952319,48.69356464812578]},"properties":{"nom":"EL","description":"Polygone 1","latitude":"48.69356464812578","longitude":"-4.097383839952319"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.102536986221444,48.69351221259058]},"properties":{"nom":"EM","description":"Polygone 1","latitude":"48.69351221259058","longitude":"-4.102536986221444"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.106197887484285,48.692515838515405]},"properties":{"nom":"EN","description":"Polygone 1","latitude":"48.692515838515405","longitude":"-4.106197887484285"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.109568285925066,48.69472448012849]},"properties":{"nom":"EO","description":"Polygone 1","latitude":"48.69472448012849","longitude":"-4.109568285925066"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.115803404112282,48.69506791354793]},"properties":{"nom":"EP","description":"Polygone 1","latitude":"48.69506791354793","longitude":"-4.115803404112282"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.118098969264236,48.692778728280935]},"properties":{"nom":"EQ","description":"Polygone 1","latitude":"48.692778728280935","longitude":"-4.118098969264236"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.12511664716867,48.693877169595176]},"properties":{"nom":"ER","description":"Polygone 1","latitude":"48.693877169595176","longitude":"-4.12511664716867"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.127837461875522,48.69361476668908]},"properties":{"nom":"ES","description":"Polygone 1","latitude":"48.69361476668908","longitude":"-4.127837461875522"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.131236501370729,48.6960475956426]},"properties":{"nom":"ET","description":"Polygone 1","latitude":"48.6960475956426","longitude":"-4.131236501370729"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.136181126707938,48.69293107079426]},"properties":{"nom":"EU","description":"Polygone 1","latitude":"48.69293107079426","longitude":"-4.136181126707938"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.142132619722753,48.69237814384752]},"properties":{"nom":"EV","description":"Polygone 1","latitude":"48.69237814384752","longitude":"-4.142132619722753"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.150020162763907,48.69217377284019]},"properties":{"nom":"EW","description":"Polygone 1","latitude":"48.69217377284019","longitude":"-4.150020162763907"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.152170300893284,48.691487051119246]},"properties":{"nom":"EX","description":"Polygone 1","latitude":"48.691487051119246","longitude":"-4.152170300893284"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.162483098525137,48.68833023827453]},"properties":{"nom":"EY","description":"Polygone 1","latitude":"48.68833023827453","longitude":"-4.162483098525137"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.174170898732186,48.657628672506775]},"properties":{"nom":"EZ","description":"Polygone 1","latitude":"48.657628672506775","longitude":"-4.174170898732186"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.409843663429304,48.633874515395604]},"properties":{"nom":"FA","description":"Polygone 1","latitude":"48.633874515395604","longitude":"-4.409843663429304"}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-4.370364497124209,48.53380508608616],[-4.373271574712479,48.47151134163559],[-4.03753485335386,48.579164636474836],[-3.89919702975027,48.603980178934115],[-3.860482328708233,48.62511389817695],[-3.858436311611334,48.629031691751045],[-3.862157259991486,48.633014015139416],[-3.870281882041237,48.63550010399696],[-3.879786359001045,48.639113643702565],[-3.895430188480503,48.64455770816115],[-3.89902273351368,48.64822789311303],[-3.902536979616769,48.654435032933826],[-3.906528075174153,48.66061643462235],[-3.904489574558275,48.6643307169305],[-3.89647573803132,48.66601900245078],[-3.890673665115296,48.667020244464325],[-3.890721315690864,48.67062455977177],[-3.892950905315848,48.67088770685571],[-3.898005277721187,48.6723935639094],[-3.8992413951649,48.67074624589731],[-3.903300809713803,48.67034264689684],[-3.907548440632195,48.66910635173531],[-3.91185396569359,48.669954398127075],[-3.914635548862354,48.67322568941628],[-3.920575104032537,48.67458696237509],[-3.924157593611878,48.669749821082725],[-3.927138109422188,48.66538094626539],[-3.927802453245391,48.66178827244388],[-3.92880004801291,48.660065331624466],[-3.930674658925236,48.657424523021],[-3.934385020441046,48.65730036039394],[-3.940574301992641,48.65682750256307],[-3.949892212356874,48.653210569309856],[-3.9518951695476,48.64983646195122],[-3.95135848409069,48.646306571150944],[-3.952791103114349,48.64456097348628],[-3.954311041643234,48.64535110107629],[-3.957178207067545,48.65093506946735],[-3.95632686509049,48.654756209794456],[-3.954939197043658,48.66049485799891],[-3.958264581105623,48.66351217516115],[-3.954301077151103,48.665175330569724],[-3.958113788215813,48.66678821578858],[-3.958288500972019,48.67004622329816],[-3.953583216471425,48.67102223996598],[-3.952154912225681,48.67280542236],[-3.954601922703807,48.67354649576719],[-3.957150323952388,48.6728667311387],[-3.962232217223142,48.674085603023535],[-3.96509885038279,48.67647290565392],[-3.968196892552599,48.67354977814375],[-3.970552500285286,48.67336152037275],[-3.971907150463719,48.67429537178488],[-3.971687730880199,48.67565139942766],[-3.968925351937541,48.67998621214178],[-3.97276835094199,48.68681279071675],[-3.969905040239144,48.687617856017994],[-3.967785856011854,48.69274164929216],[-3.97050395358365,48.693904041872074],[-3.974129066864182,48.69665141578885],[-3.976827175680581,48.699084231748806],[-3.973964059500176,48.70207052891004],[-3.97557715354335,48.70449012698265],[-3.972337757698344,48.70582333762662],[-3.974038535718974,48.710344199247295],[-3.972061362590358,48.71168433267898],[-3.969407494937729,48.71919463600953],[-3.966114995158957,48.719188628020184],[-3.964815895310649,48.72248973384656],[-3.968123622922862,48.72216808659624],[-3.970117554054281,48.7239825094888],[-3.971030085004171,48.72531725688056],[-3.974105493634571,48.72442714535237],[-3.977130032296356,48.72223266964199],[-3.98038470744471,48.72282149601802],[-3.98267568678471,48.72451484026706],[-3.983159793997456,48.72623219482621],[-3.985655519886893,48.726898196761965],[-3.988412331317411,48.727004809776105],[-3.990251104366354,48.72588975599552],[-3.992106999472123,48.723541171653366],[-3.992308257471176,48.72204072794657],[-3.990818477440011,48.71838055340067],[-3.993241558794496,48.715311146944074],[-3.99726181945054,48.71273584775902],[-4.000886986292233,48.71141716999743],[-4.005573266114372,48.715195490443925],[-4.004640753163968,48.716989015759715],[-4.007861713401779,48.72044675798358],[-4.009590286562232,48.72068101995395],[-4.012907971574204,48.71865165832863],[-4.010881803078078,48.716872551149415],[-4.013298574720932,48.713765123429766],[-4.018283788022766,48.71146515516518],[-4.02502266800395,48.710486602386844],[-4.029102910364339,48.7109751516783],[-4.032895375568785,48.712496949149184],[-4.034013864663466,48.71364906002572],[-4.035203599079426,48.71386049099469],[-4.036426674181452,48.711761570746404],[-4.035857818689737,48.70935978588029],[-4.037836186006247,48.70536884991981],[-4.040876440962449,48.70331706201061],[-4.042661395770205,48.70267658451317],[-4.044522857875245,48.70264835316387],[-4.048746772595955,48.70536952092104],[-4.051782617787177,48.70458102418029],[-4.053387641319855,48.70237110662314],[-4.054960885021424,48.69887510664347],[-4.057098904957046,48.688336149296134],[-4.047492224129947,48.6881905546806],[-4.04264615919883,48.688356681641565],[-4.05570877851515,48.685187990084636],[-4.061384711067841,48.687678086132514],[-4.063856568443375,48.68626486757381],[-4.069006699782528,48.687977416990556],[-4.066114156101222,48.68600063748565],[-4.065917761777147,48.68383188367652],[-4.06536435070835,48.68281963355705],[-4.062811851052143,48.68243638561189],[-4.063604286352126,48.680735563101265],[-4.061249339782617,48.68019915458731],[-4.060491984152113,48.67893668983929],[-4.056630622211962,48.67523642323898],[-4.055350396131191,48.67179995101334],[-4.057224936686009,48.670572879663034],[-4.057969445321888,48.675068847630506],[-4.059622862128396,48.675122344607715],[-4.06024682153259,48.67613145254186],[-4.063213863275964,48.67815002912692],[-4.064507934140134,48.677605925445725],[-4.067195178609656,48.67891661518815],[-4.068000601946539,48.68272446881325],[-4.07116708376152,48.68462241191764],[-4.080222240659125,48.689712089777736],[-4.082890717412141,48.693212237422216],[-4.0837341887691,48.69168549285934],[-4.08645810312384,48.69005696722575],[-4.08922980276701,48.69161527586137],[-4.091651149022687,48.69171173600047],[-4.095188717132302,48.686965610139666],[-4.097383839952319,48.69356464812578],[-4.102536986221444,48.69351221259058],[-4.106197887484285,48.692515838515405],[-4.109568285925066,48.69472448012849],[-4.115803404112282,48.69506791354793],[-4.118098969264236,48.692778728280935],[-4.12511664716867,48.693877169595176],[-4.127837461875522,48.69361476668908],[-4.131236501370729,48.6960475956426],[-4.136181126707938,48.69293107079426],[-4.142132619722753,48.69237814384752],[-4.150020162763907,48.69217377284019],[-4.152170300893284,48.691487051119246],[-4.162483098525137,48.68833023827453],[-4.174170898732186,48.657628672506775],[-4.409843663429304,48.633874515395604],[-4.370364497124209,48.53380508608616]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.370364497124209,48.53380508608616]},"properties":{"nom":"A","description":"Polygone 1","latitude":"48.53380508608616","longitude":"-4.370364497124209"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.373271574712479,48.47151134163559]},"properties":{"nom":"B","description":"Polygone 1","latitude":"48.47151134163559","longitude":"-4.373271574712479"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.03753485335386,48.579164636474836]},"properties":{"nom":"C","description":"Polygone 1","latitude":"48.579164636474836","longitude":"-4.03753485335386"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.89919702975027,48.603980178934115]},"properties":{"nom":"D","description":"Polygone 1","latitude":"48.603980178934115","longitude":"-3.89919702975027"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.860482328708233,48.62511389817695]},"properties":{"nom":"E","description":"Polygone 1","latitude":"48.62511389817695","longitude":"-3.860482328708233"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.858436311611334,48.629031691751045]},"properties":{"nom":"F","description":"Polygone 1","latitude":"48.629031691751045","longitude":"-3.858436311611334"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.862157259991486,48.633014015139416]},"properties":{"nom":"G","description":"Polygone 1","latitude":"48.633014015139416","longitude":"-3.862157259991486"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.870281882041237,48.63550010399696]},"properties":{"nom":"H","description":"Polygone 1","latitude":"48.63550010399696","longitude":"-3.870281882041237"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.879786359001045,48.639113643702565]},"properties":{"nom":"I","description":"Polygone 1","latitude":"48.639113643702565","longitude":"-3.879786359001045"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.895430188480503,48.64455770816115]},"properties":{"nom":"J","description":"Polygone 1","latitude":"48.64455770816115","longitude":"-3.895430188480503"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.89902273351368,48.64822789311303]},"properties":{"nom":"K","description":"Polygone 1","latitude":"48.64822789311303","longitude":"-3.89902273351368"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.902536979616769,48.654435032933826]},"properties":{"nom":"L","description":"Polygone 1","latitude":"48.654435032933826","longitude":"-3.902536979616769"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.906528075174153,48.66061643462235]},"properties":{"nom":"M","description":"Polygone 1","latitude":"48.66061643462235","longitude":"-3.906528075174153"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.904489574558275,48.6643307169305]},"properties":{"nom":"N","description":"Polygone 1","latitude":"48.6643307169305","longitude":"-3.904489574558275"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.89647573803132,48.66601900245078]},"properties":{"nom":"O","description":"Polygone 1","latitude":"48.66601900245078","longitude":"-3.89647573803132"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.890673665115296,48.667020244464325]},"properties":{"nom":"P","description":"Polygone 1","latitude":"48.667020244464325","longitude":"-3.890673665115296"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.890721315690864,48.67062455977177]},"properties":{"nom":"Q","description":"Polygone 1","latitude":"48.67062455977177","longitude":"-3.890721315690864"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.892950905315848,48.67088770685571]},"properties":{"nom":"R","description":"Polygone 1","latitude":"48.67088770685571","longitude":"-3.892950905315848"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.898005277721187,48.6723935639094]},"properties":{"nom":"S","description":"Polygone 1","latitude":"48.6723935639094","longitude":"-3.898005277721187"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.8992413951649,48.67074624589731]},"properties":{"nom":"T","description":"Polygone 1","latitude":"48.67074624589731","longitude":"-3.8992413951649"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.903300809713803,48.67034264689684]},"properties":{"nom":"U","description":"Polygone 1","latitude":"48.67034264689684","longitude":"-3.903300809713803"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.907548440632195,48.66910635173531]},"properties":{"nom":"V","description":"Polygone 1","latitude":"48.66910635173531","longitude":"-3.907548440632195"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.91185396569359,48.669954398127075]},"properties":{"nom":"W","description":"Polygone 1","latitude":"48.669954398127075","longitude":"-3.91185396569359"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.914635548862354,48.67322568941628]},"properties":{"nom":"X","description":"Polygone 1","latitude":"48.67322568941628","longitude":"-3.914635548862354"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.920575104032537,48.67458696237509]},"properties":{"nom":"Y","description":"Polygone 1","latitude":"48.67458696237509","longitude":"-3.920575104032537"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.924157593611878,48.669749821082725]},"properties":{"nom":"Z","description":"Polygone 1","latitude":"48.669749821082725","longitude":"-3.924157593611878"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.927138109422188,48.66538094626539]},"properties":{"nom":"AA","description":"Polygone 1","latitude":"48.66538094626539","longitude":"-3.927138109422188"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.927802453245391,48.66178827244388]},"properties":{"nom":"AB","description":"Polygone 1","latitude":"48.66178827244388","longitude":"-3.927802453245391"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.92880004801291,48.660065331624466]},"properties":{"nom":"AC","description":"Polygone 1","latitude":"48.660065331624466","longitude":"-3.92880004801291"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.930674658925236,48.657424523021]},"properties":{"nom":"AD","description":"Polygone 1","latitude":"48.657424523021","longitude":"-3.930674658925236"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.934385020441046,48.65730036039394]},"properties":{"nom":"AE","description":"Polygone 1","latitude":"48.65730036039394","longitude":"-3.934385020441046"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.940574301992641,48.65682750256307]},"properties":{"nom":"AF","description":"Polygone 1","latitude":"48.65682750256307","longitude":"-3.940574301992641"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.949892212356874,48.653210569309856]},"properties":{"nom":"AG","description":"Polygone 1","latitude":"48.653210569309856","longitude":"-3.949892212356874"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.9518951695476,48.64983646195122]},"properties":{"nom":"AH","description":"Polygone 1","latitude":"48.64983646195122","longitude":"-3.9518951695476"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.95135848409069,48.646306571150944]},"properties":{"nom":"AI","description":"Polygone 1","latitude":"48.646306571150944","longitude":"-3.95135848409069"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.952791103114349,48.64456097348628]},"properties":{"nom":"AJ","description":"Polygone 1","latitude":"48.64456097348628","longitude":"-3.952791103114349"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.954311041643234,48.64535110107629]},"properties":{"nom":"AK","description":"Polygone 1","latitude":"48.64535110107629","longitude":"-3.954311041643234"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.957178207067545,48.65093506946735]},"properties":{"nom":"AL","description":"Polygone 1","latitude":"48.65093506946735","longitude":"-3.957178207067545"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.95632686509049,48.654756209794456]},"properties":{"nom":"AM","description":"Polygone 1","latitude":"48.654756209794456","longitude":"-3.95632686509049"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.954939197043658,48.66049485799891]},"properties":{"nom":"AN","description":"Polygone 1","latitude":"48.66049485799891","longitude":"-3.954939197043658"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.958264581105623,48.66351217516115]},"properties":{"nom":"AO","description":"Polygone 1","latitude":"48.66351217516115","longitude":"-3.958264581105623"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.954301077151103,48.665175330569724]},"properties":{"nom":"AP","description":"Polygone 1","latitude":"48.665175330569724","longitude":"-3.954301077151103"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.958113788215813,48.66678821578858]},"properties":{"nom":"AQ","description":"Polygone 1","latitude":"48.66678821578858","longitude":"-3.958113788215813"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.958288500972019,48.67004622329816]},"properties":{"nom":"AR","description":"Polygone 1","latitude":"48.67004622329816","longitude":"-3.958288500972019"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.953583216471425,48.67102223996598]},"properties":{"nom":"AS","description":"Polygone 1","latitude":"48.67102223996598","longitude":"-3.953583216471425"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.952154912225681,48.67280542236]},"properties":{"nom":"AT","description":"Polygone 1","latitude":"48.67280542236","longitude":"-3.952154912225681"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.954601922703807,48.67354649576719]},"properties":{"nom":"AU","description":"Polygone 1","latitude":"48.67354649576719","longitude":"-3.954601922703807"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.957150323952388,48.6728667311387]},"properties":{"nom":"AV","description":"Polygone 1","latitude":"48.6728667311387","longitude":"-3.957150323952388"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.962232217223142,48.674085603023535]},"properties":{"nom":"AW","description":"Polygone 1","latitude":"48.674085603023535","longitude":"-3.962232217223142"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.96509885038279,48.67647290565392]},"properties":{"nom":"AX","description":"Polygone 1","latitude":"48.67647290565392","longitude":"-3.96509885038279"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.968196892552599,48.67354977814375]},"properties":{"nom":"AY","description":"Polygone 1","latitude":"48.67354977814375","longitude":"-3.968196892552599"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.970552500285286,48.67336152037275]},"properties":{"nom":"AZ","description":"Polygone 1","latitude":"48.67336152037275","longitude":"-3.970552500285286"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.971907150463719,48.67429537178488]},"properties":{"nom":"BA","description":"Polygone 1","latitude":"48.67429537178488","longitude":"-3.971907150463719"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.971687730880199,48.67565139942766]},"properties":{"nom":"BB","description":"Polygone 1","latitude":"48.67565139942766","longitude":"-3.971687730880199"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.968925351937541,48.67998621214178]},"properties":{"nom":"BC","description":"Polygone 1","latitude":"48.67998621214178","longitude":"-3.968925351937541"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.97276835094199,48.68681279071675]},"properties":{"nom":"BD","description":"Polygone 1","latitude":"48.68681279071675","longitude":"-3.97276835094199"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.969905040239144,48.687617856017994]},"properties":{"nom":"BE","description":"Polygone 1","latitude":"48.687617856017994","longitude":"-3.969905040239144"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.967785856011854,48.69274164929216]},"properties":{"nom":"BF","description":"Polygone 1","latitude":"48.69274164929216","longitude":"-3.967785856011854"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.97050395358365,48.693904041872074]},"properties":{"nom":"BG","description":"Polygone 1","latitude":"48.693904041872074","longitude":"-3.97050395358365"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.974129066864182,48.69665141578885]},"properties":{"nom":"BH","description":"Polygone 1","latitude":"48.69665141578885","longitude":"-3.974129066864182"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.976827175680581,48.699084231748806]},"properties":{"nom":"BI","description":"Polygone 1","latitude":"48.699084231748806","longitude":"-3.976827175680581"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.973964059500176,48.70207052891004]},"properties":{"nom":"BJ","description":"Polygone 1","latitude":"48.70207052891004","longitude":"-3.973964059500176"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.97557715354335,48.70449012698265]},"properties":{"nom":"BK","description":"Polygone 1","latitude":"48.70449012698265","longitude":"-3.97557715354335"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.972337757698344,48.70582333762662]},"properties":{"nom":"BL","description":"Polygone 1","latitude":"48.70582333762662","longitude":"-3.972337757698344"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.974038535718974,48.710344199247295]},"properties":{"nom":"BM","description":"Polygone 1","latitude":"48.710344199247295","longitude":"-3.974038535718974"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.972061362590358,48.71168433267898]},"properties":{"nom":"BN","description":"Polygone 1","latitude":"48.71168433267898","longitude":"-3.972061362590358"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.969407494937729,48.71919463600953]},"properties":{"nom":"BO","description":"Polygone 1","latitude":"48.71919463600953","longitude":"-3.969407494937729"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.966114995158957,48.719188628020184]},"properties":{"nom":"BP","description":"Polygone 1","latitude":"48.719188628020184","longitude":"-3.966114995158957"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.964815895310649,48.72248973384656]},"properties":{"nom":"BQ","description":"Polygone 1","latitude":"48.72248973384656","longitude":"-3.964815895310649"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.968123622922862,48.72216808659624]},"properties":{"nom":"BR","description":"Polygone 1","latitude":"48.72216808659624","longitude":"-3.968123622922862"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.970117554054281,48.7239825094888]},"properties":{"nom":"BS","description":"Polygone 1","latitude":"48.7239825094888","longitude":"-3.970117554054281"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.971030085004171,48.72531725688056]},"properties":{"nom":"BT","description":"Polygone 1","latitude":"48.72531725688056","longitude":"-3.971030085004171"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.974105493634571,48.72442714535237]},"properties":{"nom":"BU","description":"Polygone 1","latitude":"48.72442714535237","longitude":"-3.974105493634571"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.977130032296356,48.72223266964199]},"properties":{"nom":"BV","description":"Polygone 1","latitude":"48.72223266964199","longitude":"-3.977130032296356"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.98038470744471,48.72282149601802]},"properties":{"nom":"BW","description":"Polygone 1","latitude":"48.72282149601802","longitude":"-3.98038470744471"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.98267568678471,48.72451484026706]},"properties":{"nom":"BX","description":"Polygone 1","latitude":"48.72451484026706","longitude":"-3.98267568678471"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.983159793997456,48.72623219482621]},"properties":{"nom":"BY","description":"Polygone 1","latitude":"48.72623219482621","longitude":"-3.983159793997456"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.985655519886893,48.726898196761965]},"properties":{"nom":"BZ","description":"Polygone 1","latitude":"48.726898196761965","longitude":"-3.985655519886893"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.988412331317411,48.727004809776105]},"properties":{"nom":"CA","description":"Polygone 1","latitude":"48.727004809776105","longitude":"-3.988412331317411"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.990251104366354,48.72588975599552]},"properties":{"nom":"CB","description":"Polygone 1","latitude":"48.72588975599552","longitude":"-3.990251104366354"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.992106999472123,48.723541171653366]},"properties":{"nom":"CC","description":"Polygone 1","latitude":"48.723541171653366","longitude":"-3.992106999472123"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.992308257471176,48.72204072794657]},"properties":{"nom":"CD","description":"Polygone 1","latitude":"48.72204072794657","longitude":"-3.992308257471176"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.990818477440011,48.71838055340067]},"properties":{"nom":"CE","description":"Polygone 1","latitude":"48.71838055340067","longitude":"-3.990818477440011"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.993241558794496,48.715311146944074]},"properties":{"nom":"CF","description":"Polygone 1","latitude":"48.715311146944074","longitude":"-3.993241558794496"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-3.99726181945054,48.71273584775902]},"properties":{"nom":"CG","description":"Polygone 1","latitude":"48.71273584775902","longitude":"-3.99726181945054"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.000886986292233,48.71141716999743]},"properties":{"nom":"CH","description":"Polygone 1","latitude":"48.71141716999743","longitude":"-4.000886986292233"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.005573266114372,48.715195490443925]},"properties":{"nom":"CI","description":"Polygone 1","latitude":"48.715195490443925","longitude":"-4.005573266114372"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.004640753163968,48.716989015759715]},"properties":{"nom":"CJ","description":"Polygone 1","latitude":"48.716989015759715","longitude":"-4.004640753163968"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.007861713401779,48.72044675798358]},"properties":{"nom":"CK","description":"Polygone 1","latitude":"48.72044675798358","longitude":"-4.007861713401779"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.009590286562232,48.72068101995395]},"properties":{"nom":"CL","description":"Polygone 1","latitude":"48.72068101995395","longitude":"-4.009590286562232"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.012907971574204,48.71865165832863]},"properties":{"nom":"CM","description":"Polygone 1","latitude":"48.71865165832863","longitude":"-4.012907971574204"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.010881803078078,48.716872551149415]},"properties":{"nom":"CN","description":"Polygone 1","latitude":"48.716872551149415","longitude":"-4.010881803078078"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.013298574720932,48.713765123429766]},"properties":{"nom":"CO","description":"Polygone 1","latitude":"48.713765123429766","longitude":"-4.013298574720932"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.018283788022766,48.71146515516518]},"properties":{"nom":"CP","description":"Polygone 1","latitude":"48.71146515516518","longitude":"-4.018283788022766"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.02502266800395,48.710486602386844]},"properties":{"nom":"CQ","description":"Polygone 1","latitude":"48.710486602386844","longitude":"-4.02502266800395"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.029102910364339,48.7109751516783]},"properties":{"nom":"CR","description":"Polygone 1","latitude":"48.7109751516783","longitude":"-4.029102910364339"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.032895375568785,48.712496949149184]},"properties":{"nom":"CS","description":"Polygone 1","latitude":"48.712496949149184","longitude":"-4.032895375568785"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.034013864663466,48.71364906002572]},"properties":{"nom":"CT","description":"Polygone 1","latitude":"48.71364906002572","longitude":"-4.034013864663466"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.035203599079426,48.71386049099469]},"properties":{"nom":"CU","description":"Polygone 1","latitude":"48.71386049099469","longitude":"-4.035203599079426"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.036426674181452,48.711761570746404]},"properties":{"nom":"CV","description":"Polygone 1","latitude":"48.711761570746404","longitude":"-4.036426674181452"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.035857818689737,48.70935978588029]},"properties":{"nom":"CW","description":"Polygone 1","latitude":"48.70935978588029","longitude":"-4.035857818689737"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.037836186006247,48.70536884991981]},"properties":{"nom":"CX","description":"Polygone 1","latitude":"48.70536884991981","longitude":"-4.037836186006247"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.040876440962449,48.70331706201061]},"properties":{"nom":"CY","description":"Polygone 1","latitude":"48.70331706201061","longitude":"-4.040876440962449"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.042661395770205,48.70267658451317]},"properties":{"nom":"CZ","description":"Polygone 1","latitude":"48.70267658451317","longitude":"-4.042661395770205"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.044522857875245,48.70264835316387]},"properties":{"nom":"DA","description":"Polygone 1","latitude":"48.70264835316387","longitude":"-4.044522857875245"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.048746772595955,48.70536952092104]},"properties":{"nom":"DB","description":"Polygone 1","latitude":"48.70536952092104","longitude":"-4.048746772595955"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.051782617787177,48.70458102418029]},"properties":{"nom":"DC","description":"Polygone 1","latitude":"48.70458102418029","longitude":"-4.051782617787177"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.053387641319855,48.70237110662314]},"properties":{"nom":"DD","description":"Polygone 1","latitude":"48.70237110662314","longitude":"-4.053387641319855"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.054960885021424,48.69887510664347]},"properties":{"nom":"DE","description":"Polygone 1","latitude":"48.69887510664347","longitude":"-4.054960885021424"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.057098904957046,48.688336149296134]},"properties":{"nom":"DF","description":"Polygone 1","latitude":"48.688336149296134","longitude":"-4.057098904957046"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.047492224129947,48.6881905546806]},"properties":{"nom":"DG","description":"Polygone 1","latitude":"48.6881905546806","longitude":"-4.047492224129947"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.04264615919883,48.688356681641565]},"properties":{"nom":"DH","description":"Polygone 1","latitude":"48.688356681641565","longitude":"-4.04264615919883"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.05570877851515,48.685187990084636]},"properties":{"nom":"DI","description":"Polygone 1","latitude":"48.685187990084636","longitude":"-4.05570877851515"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.061384711067841,48.687678086132514]},"properties":{"nom":"DJ","description":"Polygone 1","latitude":"48.687678086132514","longitude":"-4.061384711067841"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.063856568443375,48.68626486757381]},"properties":{"nom":"DK","description":"Polygone 1","latitude":"48.68626486757381","longitude":"-4.063856568443375"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.069006699782528,48.687977416990556]},"properties":{"nom":"DL","description":"Polygone 1","latitude":"48.687977416990556","longitude":"-4.069006699782528"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.066114156101222,48.68600063748565]},"properties":{"nom":"DM","description":"Polygone 1","latitude":"48.68600063748565","longitude":"-4.066114156101222"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.065917761777147,48.68383188367652]},"properties":{"nom":"DN","description":"Polygone 1","latitude":"48.68383188367652","longitude":"-4.065917761777147"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.06536435070835,48.68281963355705]},"properties":{"nom":"DO","description":"Polygone 1","latitude":"48.68281963355705","longitude":"-4.06536435070835"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.062811851052143,48.68243638561189]},"properties":{"nom":"DP","description":"Polygone 1","latitude":"48.68243638561189","longitude":"-4.062811851052143"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.063604286352126,48.680735563101265]},"properties":{"nom":"DQ","description":"Polygone 1","latitude":"48.680735563101265","longitude":"-4.063604286352126"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.061249339782617,48.68019915458731]},"properties":{"nom":"DR","description":"Polygone 1","latitude":"48.68019915458731","longitude":"-4.061249339782617"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.060491984152113,48.67893668983929]},"properties":{"nom":"DS","description":"Polygone 1","latitude":"48.67893668983929","longitude":"-4.060491984152113"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.056630622211962,48.67523642323898]},"properties":{"nom":"DT","description":"Polygone 1","latitude":"48.67523642323898","longitude":"-4.056630622211962"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.055350396131191,48.67179995101334]},"properties":{"nom":"DU","description":"Polygone 1","latitude":"48.67179995101334","longitude":"-4.055350396131191"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.057224936686009,48.670572879663034]},"properties":{"nom":"DV","description":"Polygone 1","latitude":"48.670572879663034","longitude":"-4.057224936686009"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.057969445321888,48.675068847630506]},"properties":{"nom":"DW","description":"Polygone 1","latitude":"48.675068847630506","longitude":"-4.057969445321888"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.059622862128396,48.675122344607715]},"properties":{"nom":"DX","description":"Polygone 1","latitude":"48.675122344607715","longitude":"-4.059622862128396"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.06024682153259,48.67613145254186]},"properties":{"nom":"DY","description":"Polygone 1","latitude":"48.67613145254186","longitude":"-4.06024682153259"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.063213863275964,48.67815002912692]},"properties":{"nom":"DZ","description":"Polygone 1","latitude":"48.67815002912692","longitude":"-4.063213863275964"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.064507934140134,48.677605925445725]},"properties":{"nom":"EA","description":"Polygone 1","latitude":"48.677605925445725","longitude":"-4.064507934140134"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.067195178609656,48.67891661518815]},"properties":{"nom":"EB","description":"Polygone 1","latitude":"48.67891661518815","longitude":"-4.067195178609656"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.068000601946539,48.68272446881325]},"properties":{"nom":"EC","description":"Polygone 1","latitude":"48.68272446881325","longitude":"-4.068000601946539"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.07116708376152,48.68462241191764]},"properties":{"nom":"ED","description":"Polygone 1","latitude":"48.68462241191764","longitude":"-4.07116708376152"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.080222240659125,48.689712089777736]},"properties":{"nom":"EE","description":"Polygone 1","latitude":"48.689712089777736","longitude":"-4.080222240659125"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.082890717412141,48.693212237422216]},"properties":{"nom":"EF","description":"Polygone 1","latitude":"48.693212237422216","longitude":"-4.082890717412141"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.0837341887691,48.69168549285934]},"properties":{"nom":"EG","description":"Polygone 1","latitude":"48.69168549285934","longitude":"-4.0837341887691"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.08645810312384,48.69005696722575]},"properties":{"nom":"EH","description":"Polygone 1","latitude":"48.69005696722575","longitude":"-4.08645810312384"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.08922980276701,48.69161527586137]},"properties":{"nom":"EI","description":"Polygone 1","latitude":"48.69161527586137","longitude":"-4.08922980276701"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.091651149022687,48.69171173600047]},"properties":{"nom":"EJ","description":"Polygone 1","latitude":"48.69171173600047","longitude":"-4.091651149022687"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.095188717132302,48.686965610139666]},"properties":{"nom":"EK","description":"Polygone 1","latitude":"48.686965610139666","longitude":"-4.095188717132302"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.097383839952319,48.69356464812578]},"properties":{"nom":"EL","description":"Polygone 1","latitude":"48.69356464812578","longitude":"-4.097383839952319"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.102536986221444,48.69351221259058]},"properties":{"nom":"EM","description":"Polygone 1","latitude":"48.69351221259058","longitude":"-4.102536986221444"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.106197887484285,48.692515838515405]},"properties":{"nom":"EN","description":"Polygone 1","latitude":"48.692515838515405","longitude":"-4.106197887484285"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.109568285925066,48.69472448012849]},"properties":{"nom":"EO","description":"Polygone 1","latitude":"48.69472448012849","longitude":"-4.109568285925066"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.115803404112282,48.69506791354793]},"properties":{"nom":"EP","description":"Polygone 1","latitude":"48.69506791354793","longitude":"-4.115803404112282"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.118098969264236,48.692778728280935]},"properties":{"nom":"EQ","description":"Polygone 1","latitude":"48.692778728280935","longitude":"-4.118098969264236"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.12511664716867,48.693877169595176]},"properties":{"nom":"ER","description":"Polygone 1","latitude":"48.693877169595176","longitude":"-4.12511664716867"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.127837461875522,48.69361476668908]},"properties":{"nom":"ES","description":"Polygone 1","latitude":"48.69361476668908","longitude":"-4.127837461875522"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.131236501370729,48.6960475956426]},"properties":{"nom":"ET","description":"Polygone 1","latitude":"48.6960475956426","longitude":"-4.131236501370729"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.136181126707938,48.69293107079426]},"properties":{"nom":"EU","description":"Polygone 1","latitude":"48.69293107079426","longitude":"-4.136181126707938"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.142132619722753,48.69237814384752]},"properties":{"nom":"EV","description":"Polygone 1","latitude":"48.69237814384752","longitude":"-4.142132619722753"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.150020162763907,48.69217377284019]},"properties":{"nom":"EW","description":"Polygone 1","latitude":"48.69217377284019","longitude":"-4.150020162763907"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.152170300893284,48.691487051119246]},"properties":{"nom":"EX","description":"Polygone 1","latitude":"48.691487051119246","longitude":"-4.152170300893284"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.162483098525137,48.68833023827453]},"properties":{"nom":"EY","description":"Polygone 1","latitude":"48.68833023827453","longitude":"-4.162483098525137"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.174170898732186,48.657628672506775]},"properties":{"nom":"EZ","description":"Polygone 1","latitude":"48.657628672506775","longitude":"-4.174170898732186"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-4.409843663429304,48.633874515395604]},"properties":{"nom":"FA","description":"Polygone 1","latitude":"48.633874515395604","longitude":"-4.409843663429304"}}]},"geojson_origine_geo_systeme_id":"4326","geojson4326_forages":null,"geojson_origine_forages":null,"surface":3}</perimetre> <id>"test"</id> - <titretypeid>"axm"</titretypeid> + <machineinfo>{"_titreTypeId":"axm","_demarcheTypeId":"oct","_demarcheId":"demarcheId"}</machineinfo> <style> { "minHeight": "400px" diff --git a/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_Default.html b/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_Default.html index aa81f34eb..69ed19ac8 100644 --- a/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_Default.html +++ b/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_Default.html @@ -305,10 +305,10 @@ </ul> <div id="tabpanel-carte-test-panel" class="fr-tabs__panel fr-tabs__panel--selected" role="tabpanel" aria-labelledby="tabpanel-carte-test" tabindex="0"> <div style="display: flex; flex-direction: column;"> - <mocked-map perimetre="[object Object]" id="test" titretypeid="axm" style="min-height: 400px;" class="fr-mb-1w" maxmarkers="20" neighbours="[object Object]"> + <mocked-map perimetre="[object Object]" id="test" machineinfo="[object Object]" style="min-height: 400px;" class="fr-mb-1w" maxmarkers="20" neighbours="[object Object]"> <perimetre>{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-52.5660583466962,4.23944263425535],[-52.5591878553913,4.22269896902571],[-52.5550566725882,4.22438936251509],[-52.5619271168799,4.24113309117193],[-52.5660583466962,4.23944263425535]]]]}},"geojson4326_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5660583466962,4.23944263425535]},"properties":{"nom":"A","description":"Polygone 1","latitude":"4.23944263425535","longitude":"-52.5660583466962"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5591878553913,4.22269896902571]},"properties":{"nom":"B","description":"Polygone 1","latitude":"4.22269896902571","longitude":"-52.5591878553913"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5550566725882,4.22438936251509]},"properties":{"nom":"C","description":"Polygone 1","latitude":"4.22438936251509","longitude":"-52.5550566725882"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5619271168799,4.24113309117193]},"properties":{"nom":"D","description":"Polygone 1","latitude":"4.24113309117193","longitude":"-52.5619271168799"}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-52.5660583466962,4.23944263425535],[-52.5591878553913,4.22269896902571],[-52.5550566725882,4.22438936251509],[-52.5619271168799,4.24113309117193],[-52.5660583466962,4.23944263425535]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5660583466962,4.23944263425535]},"properties":{"nom":"A","description":"Polygone 1","latitude":"4.23944263425535","longitude":"-52.5660583466962"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5591878553913,4.22269896902571]},"properties":{"nom":"B","description":"Polygone 1","latitude":"4.22269896902571","longitude":"-52.5591878553913"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5550566725882,4.22438936251509]},"properties":{"nom":"C","description":"Polygone 1","latitude":"4.22438936251509","longitude":"-52.5550566725882"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5619271168799,4.24113309117193]},"properties":{"nom":"D","description":"Polygone 1","latitude":"4.24113309117193","longitude":"-52.5619271168799"}}]},"geojson_origine_geo_systeme_id":"4326","geojson4326_forages":null,"geojson_origine_forages":null,"surface":3}</perimetre> <id>"test"</id> - <titretypeid>"axm"</titretypeid> + <machineinfo>{"_titreTypeId":"axm","_demarcheTypeId":"oct","_demarcheId":"demarcheId"}</machineinfo> <style> { "minHeight": "400px" diff --git a/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_Multiple.html b/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_Multiple.html index 0660c4d16..f4c934bc0 100644 --- a/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_Multiple.html +++ b/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_Multiple.html @@ -305,10 +305,10 @@ </ul> <div id="tabpanel-carte-test-panel" class="fr-tabs__panel fr-tabs__panel--selected" role="tabpanel" aria-labelledby="tabpanel-carte-test" tabindex="0"> <div style="display: flex; flex-direction: column;"> - <mocked-map perimetre="[object Object]" id="test" titretypeid="axm" style="min-height: 400px;" class="fr-mb-1w" maxmarkers="20" neighbours="[object Object]"> + <mocked-map perimetre="[object Object]" id="test" machineinfo="[object Object]" style="min-height: 400px;" class="fr-mb-1w" maxmarkers="20" neighbours="[object Object]"> <perimetre>{"geojson4326_perimetre":{"properties":{},"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[-53.58181013905019,3.8309654861273],[-53.58178306390299,3.8219278216269807],[-53.572785590706495,3.82195493825841],[-53.57281257175149,3.8309926670647294],[-53.58181013905019,3.8309654861273]]],[[[-53.60031408473134,3.8224780986447566],[-53.59891645305842,3.8181831495446303],[-53.58181205656814,3.82379854768971],[-53.58320964990986,3.828093576227541],[-53.60031408473134,3.8224780986447566]]],[[[-53.583861926103765,3.8502114455117433],[-53.592379712320195,3.834289122043602],[-53.588417035915334,3.8321501920354253],[-53.57989914401643,3.8480725119510217],[-53.583861926103765,3.8502114455117433]]]]}},"geojson_origine_perimetre":{"properties":{},"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[-53.58181013905019,3.8309654861273],[-53.58178306390299,3.8219278216269807],[-53.572785590706495,3.82195493825841],[-53.57281257175149,3.8309926670647294],[-53.58181013905019,3.8309654861273]]],[[[-53.60031408473134,3.8224780986447566],[-53.59891645305842,3.8181831495446303],[-53.58181205656814,3.82379854768971],[-53.58320964990986,3.828093576227541],[-53.60031408473134,3.8224780986447566]]],[[[-53.583861926103765,3.8502114455117433],[-53.592379712320195,3.834289122043602],[-53.588417035915334,3.8321501920354253],[-53.57989914401643,3.8480725119510217],[-53.583861926103765,3.8502114455117433]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.58181013905019,3.8309654861273]},"properties":{"nom":"A","description":"Polygone 1","latitude":"3.8309654861273","longitude":"-53.58181013905019"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.58178306390299,3.8219278216269807]},"properties":{"nom":"B","description":"Polygone 1","latitude":"3.8219278216269807","longitude":"-53.58178306390299"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.572785590706495,3.82195493825841]},"properties":{"nom":"C","description":"Polygone 1","latitude":"3.82195493825841","longitude":"-53.572785590706495"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.57281257175149,3.8309926670647294]},"properties":{"nom":"D","description":"Polygone 1","latitude":"3.8309926670647294","longitude":"-53.57281257175149"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.60031408473134,3.8224780986447566]},"properties":{"nom":"E","description":"Polygone 2","latitude":"3.8224780986447566","longitude":"-53.60031408473134"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.59891645305842,3.8181831495446303]},"properties":{"nom":"F","description":"Polygone 2","latitude":"3.8181831495446303","longitude":"-53.59891645305842"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.58181205656814,3.82379854768971]},"properties":{"nom":"G","description":"Polygone 2","latitude":"3.82379854768971","longitude":"-53.58181205656814"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.58320964990986,3.828093576227541]},"properties":{"nom":"H","description":"Polygone 2","latitude":"3.828093576227541","longitude":"-53.58320964990986"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.583861926103765,3.8502114455117433]},"properties":{"nom":"I","description":"Polygone 3","latitude":"3.8502114455117433","longitude":"-53.583861926103765"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.592379712320195,3.834289122043602]},"properties":{"nom":"J","description":"Polygone 3","latitude":"3.834289122043602","longitude":"-53.592379712320195"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.588417035915334,3.8321501920354253]},"properties":{"nom":"K","description":"Polygone 3","latitude":"3.8321501920354253","longitude":"-53.588417035915334"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.57989914401643,3.8480725119510217]},"properties":{"nom":"L","description":"Polygone 3","latitude":"3.8480725119510217","longitude":"-53.57989914401643"}}]},"geojson_origine_geo_systeme_id":"4326","geojson4326_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.58181013905019,3.8309654861273]},"properties":{"nom":"A","description":"Polygone 1","latitude":"3.8309654861273","longitude":"-53.58181013905019"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.58178306390299,3.8219278216269807]},"properties":{"nom":"B","description":"Polygone 1","latitude":"3.8219278216269807","longitude":"-53.58178306390299"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.572785590706495,3.82195493825841]},"properties":{"nom":"C","description":"Polygone 1","latitude":"3.82195493825841","longitude":"-53.572785590706495"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.57281257175149,3.8309926670647294]},"properties":{"nom":"D","description":"Polygone 1","latitude":"3.8309926670647294","longitude":"-53.57281257175149"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.60031408473134,3.8224780986447566]},"properties":{"nom":"E","description":"Polygone 2","latitude":"3.8224780986447566","longitude":"-53.60031408473134"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.59891645305842,3.8181831495446303]},"properties":{"nom":"F","description":"Polygone 2","latitude":"3.8181831495446303","longitude":"-53.59891645305842"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.58181205656814,3.82379854768971]},"properties":{"nom":"G","description":"Polygone 2","latitude":"3.82379854768971","longitude":"-53.58181205656814"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.58320964990986,3.828093576227541]},"properties":{"nom":"H","description":"Polygone 2","latitude":"3.828093576227541","longitude":"-53.58320964990986"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.583861926103765,3.8502114455117433]},"properties":{"nom":"I","description":"Polygone 3","latitude":"3.8502114455117433","longitude":"-53.583861926103765"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.592379712320195,3.834289122043602]},"properties":{"nom":"J","description":"Polygone 3","latitude":"3.834289122043602","longitude":"-53.592379712320195"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.588417035915334,3.8321501920354253]},"properties":{"nom":"K","description":"Polygone 3","latitude":"3.8321501920354253","longitude":"-53.588417035915334"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.57989914401643,3.8480725119510217]},"properties":{"nom":"L","description":"Polygone 3","latitude":"3.8480725119510217","longitude":"-53.57989914401643"}}]},"geojson4326_forages":null,"geojson_origine_forages":null,"surface":3}</perimetre> <id>"test"</id> - <titretypeid>"axm"</titretypeid> + <machineinfo>{"_titreTypeId":"axm","_demarcheTypeId":"oct","_demarcheId":"demarcheId"}</machineinfo> <style> { "minHeight": "400px" diff --git a/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_NoNeighbors.html b/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_NoNeighbors.html index f061e33e4..18f657e68 100644 --- a/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_NoNeighbors.html +++ b/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_NoNeighbors.html @@ -305,10 +305,10 @@ </ul> <div id="tabpanel-carte-test-panel" class="fr-tabs__panel fr-tabs__panel--selected" role="tabpanel" aria-labelledby="tabpanel-carte-test" tabindex="0"> <div style="display: flex; flex-direction: column;"> - <mocked-map perimetre="[object Object]" id="test" titretypeid="axm" style="min-height: 400px;" class="fr-mb-1w" maxmarkers="20"> + <mocked-map perimetre="[object Object]" id="test" machineinfo="[object Object]" style="min-height: 400px;" class="fr-mb-1w" maxmarkers="20"> <perimetre>{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-52.5660583466962,4.23944263425535],[-52.5591878553913,4.22269896902571],[-52.5550566725882,4.22438936251509],[-52.5619271168799,4.24113309117193],[-52.5660583466962,4.23944263425535]]]]}},"geojson4326_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5660583466962,4.23944263425535]},"properties":{"nom":"A","description":"Polygone 1","latitude":"4.23944263425535","longitude":"-52.5660583466962"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5591878553913,4.22269896902571]},"properties":{"nom":"B","description":"Polygone 1","latitude":"4.22269896902571","longitude":"-52.5591878553913"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5550566725882,4.22438936251509]},"properties":{"nom":"C","description":"Polygone 1","latitude":"4.22438936251509","longitude":"-52.5550566725882"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5619271168799,4.24113309117193]},"properties":{"nom":"D","description":"Polygone 1","latitude":"4.24113309117193","longitude":"-52.5619271168799"}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-52.5660583466962,4.23944263425535],[-52.5591878553913,4.22269896902571],[-52.5550566725882,4.22438936251509],[-52.5619271168799,4.24113309117193],[-52.5660583466962,4.23944263425535]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5660583466962,4.23944263425535]},"properties":{"nom":"A","description":"Polygone 1","latitude":"4.23944263425535","longitude":"-52.5660583466962"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5591878553913,4.22269896902571]},"properties":{"nom":"B","description":"Polygone 1","latitude":"4.22269896902571","longitude":"-52.5591878553913"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5550566725882,4.22438936251509]},"properties":{"nom":"C","description":"Polygone 1","latitude":"4.22438936251509","longitude":"-52.5550566725882"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5619271168799,4.24113309117193]},"properties":{"nom":"D","description":"Polygone 1","latitude":"4.24113309117193","longitude":"-52.5619271168799"}}]},"geojson_origine_geo_systeme_id":"4326","geojson4326_forages":null,"geojson_origine_forages":null,"surface":3}</perimetre> <id>"test"</id> - <titretypeid>"axm"</titretypeid> + <machineinfo>{"_titreTypeId":"axm","_demarcheTypeId":"oct","_demarcheId":"demarcheId"}</machineinfo> <style> { "minHeight": "400px" diff --git a/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_PolygonWithLacune.html b/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_PolygonWithLacune.html index 497fddec1..2f51e5ee6 100644 --- a/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_PolygonWithLacune.html +++ b/packages/ui/src/components/_common/dsfr-perimetre.stories_snapshots_PolygonWithLacune.html @@ -305,10 +305,10 @@ </ul> <div id="tabpanel-carte-test-panel" class="fr-tabs__panel fr-tabs__panel--selected" role="tabpanel" aria-labelledby="tabpanel-carte-test" tabindex="0"> <div style="display: flex; flex-direction: column;"> - <mocked-map perimetre="[object Object]" id="test" titretypeid="axm" style="min-height: 400px;" class="fr-mb-1w" maxmarkers="20" neighbours="[object Object]"> + <mocked-map perimetre="[object Object]" id="test" machineinfo="[object Object]" style="min-height: 400px;" class="fr-mb-1w" maxmarkers="20" neighbours="[object Object]"> <perimetre>{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-52.5660583466962,4.23944263425535],[-52.5591878553913,4.22269896902571],[-52.5550566725882,4.22438936251509],[-52.5619271168799,4.24113309117193],[-52.5660583466962,4.23944263425535]],[[-52.563,4.236],[-52.5591878553913,4.227],[-52.561,4.236],[-52.563,4.236]]]]}},"geojson4326_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5660583466962,4.23944263425535]},"properties":{"nom":"A","description":"Polygone 1","latitude":"4.23944263425535","longitude":"-52.5660583466962"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5591878553913,4.22269896902571]},"properties":{"nom":"B","description":"Polygone 1","latitude":"4.22269896902571","longitude":"-52.5591878553913"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5550566725882,4.22438936251509]},"properties":{"nom":"C","description":"Polygone 1","latitude":"4.22438936251509","longitude":"-52.5550566725882"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5619271168799,4.24113309117193]},"properties":{"nom":"D","description":"Polygone 1","latitude":"4.24113309117193","longitude":"-52.5619271168799"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.563,4.236]},"properties":{"nom":"E","description":"Polygone 1 - Lacune 1","latitude":"4.236","longitude":"-52.563"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5591878553913,4.227]},"properties":{"nom":"F","description":"Polygone 1 - Lacune 1","latitude":"4.227","longitude":"-52.5591878553913"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.561,4.236]},"properties":{"nom":"G","description":"Polygone 1 - Lacune 1","latitude":"4.236","longitude":"-52.561"}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-52.5660583466962,4.23944263425535],[-52.5591878553913,4.22269896902571],[-52.5550566725882,4.22438936251509],[-52.5619271168799,4.24113309117193],[-52.5660583466962,4.23944263425535]],[[-52.563,4.236],[-52.5591878553913,4.227],[-52.561,4.236],[-52.563,4.236]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5660583466962,4.23944263425535]},"properties":{"nom":"A","description":"Polygone 1","latitude":"4.23944263425535","longitude":"-52.5660583466962"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5591878553913,4.22269896902571]},"properties":{"nom":"B","description":"Polygone 1","latitude":"4.22269896902571","longitude":"-52.5591878553913"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5550566725882,4.22438936251509]},"properties":{"nom":"C","description":"Polygone 1","latitude":"4.22438936251509","longitude":"-52.5550566725882"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5619271168799,4.24113309117193]},"properties":{"nom":"D","description":"Polygone 1","latitude":"4.24113309117193","longitude":"-52.5619271168799"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.563,4.236]},"properties":{"nom":"E","description":"Polygone 1 - Lacune 1","latitude":"4.236","longitude":"-52.563"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.5591878553913,4.227]},"properties":{"nom":"F","description":"Polygone 1 - Lacune 1","latitude":"4.227","longitude":"-52.5591878553913"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-52.561,4.236]},"properties":{"nom":"G","description":"Polygone 1 - Lacune 1","latitude":"4.236","longitude":"-52.561"}}]},"geojson_origine_geo_systeme_id":"4326","geojson4326_forages":null,"geojson_origine_forages":null,"surface":3}</perimetre> <id>"test"</id> - <titretypeid>"axm"</titretypeid> + <machineinfo>{"_titreTypeId":"axm","_demarcheTypeId":"oct","_demarcheId":"demarcheId"}</machineinfo> <style> { "minHeight": "400px" diff --git a/packages/ui/src/components/_common/dsfr-perimetre.tsx b/packages/ui/src/components/_common/dsfr-perimetre.tsx index 5fe77a1aa..ca14fb204 100644 --- a/packages/ui/src/components/_common/dsfr-perimetre.tsx +++ b/packages/ui/src/components/_common/dsfr-perimetre.tsx @@ -8,9 +8,9 @@ import { ApiClient } from '../../api/api-client' import { TabCaminoTable, transformMultipolygonToPoints } from './dsfr-perimetre-table' import { OmitDistributive, isNotNullNorUndefined } from 'camino-common/src/typescript-tools' import { GeoSystemeId } from 'camino-common/src/static/geoSystemes' -import { TitreTypeId } from 'camino-common/src/static/titresTypes' import { KM2 } from 'camino-common/src/number' import { CaminoRouter } from '@/typings/vue-router' +import { MachineInfo } from 'camino-common/src/machines' export type TabId = 'carte' | 'points' type Props = { @@ -25,7 +25,7 @@ type Props = { surface: KM2 | null } titreSlug: TitreSlug - titreTypeId: TitreTypeId + machineInfo: MachineInfo id: string initTab?: TabId class?: HTMLAttributes['class'] @@ -116,7 +116,7 @@ const TabCaminoMap = defineComponent<TabCaminoMapProps>(props => { return () => ( <div style={{ display: 'flex', flexDirection: 'column' }}> - <DemarcheMap perimetre={props.perimetre} id={props.id} titreTypeId={props.titreTypeId} style={{ minHeight: '400px' }} class="fr-mb-1w" maxMarkers={maxRows} neighbours={neighbours} /> + <DemarcheMap perimetre={props.perimetre} id={props.id} machineInfo={props.machineInfo} style={{ minHeight: '400px' }} class="fr-mb-1w" maxMarkers={maxRows} neighbours={neighbours} /> <div style={{ display: 'flex' }}> {isNotNullNorUndefined(props.perimetre.surface) ? <div class="fr-text--md">Surface : {props.perimetre.surface} Km²</div> : null} <div style={{ marginLeft: 'auto' }}> @@ -146,7 +146,7 @@ const TabCaminoMap = defineComponent<TabCaminoMapProps>(props => { }) // @ts-ignore waiting for https://github.com/vuejs/core/issues/7833 -DsfrPerimetre.props = ['id', 'perimetre', 'apiClient', 'titreSlug', 'titreTypeId', 'router', 'initTab', 'calculateNeighbours'] +DsfrPerimetre.props = ['id', 'perimetre', 'apiClient', 'titreSlug', 'machineInfo', 'router', 'initTab', 'calculateNeighbours'] // @ts-ignore waiting for https://github.com/vuejs/core/issues/7833 -TabCaminoMap.props = ['id', 'perimetre', 'apiClient', 'titreSlug', 'titreTypeId', 'router', 'initTab', 'calculateNeighbours'] +TabCaminoMap.props = ['id', 'perimetre', 'apiClient', 'titreSlug', 'machineInfo', 'router', 'initTab', 'calculateNeighbours'] diff --git a/packages/ui/src/components/dashboard/pure-super-dashboard.stories.tsx b/packages/ui/src/components/dashboard/pure-super-dashboard.stories.tsx index a3b7dfb34..1a33bc935 100644 --- a/packages/ui/src/components/dashboard/pure-super-dashboard.stories.tsx +++ b/packages/ui/src/components/dashboard/pure-super-dashboard.stories.tsx @@ -51,6 +51,7 @@ const titres: SuperTitre[] = [ etape_date: caminoDateValidator.parse('1810-01-01'), etape_slug: etapeSlugValidator.parse('m-cx-aachen-1810-oct01-mfr01'), etape_type_id: 'mfr', + machine_id: 'AncienLogigrammeOctroiARM', }, { titre_nom: 'Amadis 5', @@ -62,6 +63,7 @@ const titres: SuperTitre[] = [ etape_date: caminoDateValidator.parse('2022-01-01'), etape_slug: etapeSlugValidator.parse('m-ax-amadis-5-2022-oct01-mfr01'), etape_type_id: 'asc', + machine_id: 'ProcedureSpecifique', }, ] diff --git a/packages/ui/src/components/dashboard/pure-super-dashboard.stories_snapshots_TableauPleinBrouillon.html b/packages/ui/src/components/dashboard/pure-super-dashboard.stories_snapshots_TableauPleinBrouillon.html index 91ad57211..be512670b 100644 --- a/packages/ui/src/components/dashboard/pure-super-dashboard.stories_snapshots_TableauPleinBrouillon.html +++ b/packages/ui/src/components/dashboard/pure-super-dashboard.stories_snapshots_TableauPleinBrouillon.html @@ -31,6 +31,7 @@ <th scope="col">Statut du titre</th> <th scope="col">Étape en brouillon</th> <th scope="col">Date de l'étape</th> + <th scope="col">Machine associée</th> </tr> </thead> <tbody> @@ -46,6 +47,7 @@ </td> <td><span class="">Demande</span></td> <td><span class="">1810-01-01</span></td> + <td><span class="">Ancien logigramme octroi d'ARM</span></td> </tr> <tr> <td><a href="/mocked-href" title="Amadis 5" aria-label="Amadis 5">Amadis 5</a></td> @@ -59,6 +61,7 @@ </td> <td><span class="">Avis des services et commissions consultatives</span></td> <td><span class="">2022-01-01</span></td> + <td><span class="">Procédure spécifique</span></td> </tr> </tbody> </table> diff --git a/packages/ui/src/components/dashboard/pure-super-dashboard.tsx b/packages/ui/src/components/dashboard/pure-super-dashboard.tsx index ec83dd855..7809e9695 100644 --- a/packages/ui/src/components/dashboard/pure-super-dashboard.tsx +++ b/packages/ui/src/components/dashboard/pure-super-dashboard.tsx @@ -8,7 +8,7 @@ import { ComponentColumnData, JSXElementColumnData, TableRow, TextColumnData } f import { DashboardApiClient } from './dashboard-api-client' import { User } from 'camino-common/src/roles' import { PageContentHeader } from '../_common/page-header-content' -import { exhaustiveCheck, isNotNullNorUndefinedNorEmpty } from 'camino-common/src/typescript-tools' +import { exhaustiveCheck, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty } from 'camino-common/src/typescript-tools' import { CaminoRouterLink, routerQueryToString } from '@/router/camino-router-link' import { DemarchesTypes } from 'camino-common/src/static/demarchesTypes' import { capitalize } from 'camino-common/src/strings' @@ -25,7 +25,17 @@ import { ActivitesTypes } from 'camino-common/src/static/activitesTypes' import { ActiviteStatut } from '../_common/activite-statut' import { fr } from '@codegouvfr/react-dsfr' import { ACTIVITES_STATUTS_IDS } from 'camino-common/src/static/activitesStatuts' +import { CaminoMachineId } from 'camino-common/src/validators/machine' +const machineIdToText = { + AncienLogigrammeOctroiARM: "Ancien logigramme octroi d'ARM", + AncienLogigrammeOctroiAXM: "Ancien logigramme octroi d'AEX", + AncienLogigrammeOctroiPRM: 'Ancien logigramme octroi de PRM', + AncienLogigrammeProlongationAXM: "Ancien logigramme prolongation d'AEX", + AncienLogigrammeRenonciationEtProlongationARM: "Ancien logigramme renonciation et prolongation d'ARM", + ProcedureSimplifiee: 'Procédure simplifiée', + ProcedureSpecifique: 'Procédure spécifique', +} as const satisfies Record<CaminoMachineId, string> interface Props { apiClient: Pick<DashboardApiClient, 'getTitresAvecEtapeEnBrouillon' | 'getActivitesSuper'> user: User @@ -40,6 +50,7 @@ const brouillonsColumns = [ { id: 'titre_statut', contentTitle: 'Statut du titre' }, { id: 'etape_brouillon', contentTitle: 'Étape en brouillon' }, { id: 'etape_date', contentTitle: "Date de l'étape" }, + { id: 'machine', contentTitle: 'Machine associée' }, ] as const satisfies Column[] type BrouillonColumnId = (typeof brouillonsColumns)[number]['id'] @@ -124,6 +135,7 @@ export const PureSuperDashboard = defineComponent<Props>(props => { titre_statut: statutCell(titre), etape_brouillon: { type: 'text', value: capitalize(EtapesTypes[titre.etape_type_id].nom) }, etape_date: { type: 'text', value: titre.etape_date }, + machine: { type: 'text', value: isNotNullNorUndefined(titre.machine_id) ? machineIdToText[titre.machine_id] : 'TDE' }, } return { diff --git a/packages/ui/src/components/demarche-resultat-mise-en-concurrence.tsx b/packages/ui/src/components/demarche-resultat-mise-en-concurrence.tsx index 45f18f27f..20e43ddef 100644 --- a/packages/ui/src/components/demarche-resultat-mise-en-concurrence.tsx +++ b/packages/ui/src/components/demarche-resultat-mise-en-concurrence.tsx @@ -10,6 +10,7 @@ import { useRoute, useRouter } from 'vue-router' import { useState } from '@/utils/vue-tsx-utils' import { inject } from 'vue' import { entreprisesKey, userKey } from '@/moi' +import { MachineInfo } from 'camino-common/src/machines' export const DemarcheResultatMiseEnConcurrence = defineComponent(() => { const currentRoute = useRoute<'resultatMiseEnConcurrence'>() @@ -28,7 +29,7 @@ type Props = { } const PureDemarcheResultatMiseEnConcurrence = defineComponent<Props>(props => { - const [data, setData] = useState<AsyncData<GetResultatMiseEnConcurrence>>({ status: 'LOADING' }) + const [data, setData] = useState<AsyncData<{ pivot: GetResultatMiseEnConcurrence; machineInfo: MachineInfo }>>({ status: 'LOADING' }) const entreprises = inject(entreprisesKey, ref([])) const user = inject(userKey) @@ -42,7 +43,12 @@ const PureDemarcheResultatMiseEnConcurrence = defineComponent<Props>(props => { error: result, }) } else { - setData({ status: 'LOADED', value: result }) + const machineInfo = MachineInfo.withMachineId(result.titreTypeId, result.demarcheTypeId, result.demarcheId, result.machineId) + if (!machineInfo.valid) { + setData({ status: 'NEW_ERROR', error: { message: machineInfo.error } }) + } else { + setData({ status: 'LOADED', value: { pivot: result, machineInfo: machineInfo.value } }) + } } }) @@ -60,7 +66,8 @@ const PureDemarcheResultatMiseEnConcurrence = defineComponent<Props>(props => { }, }} user={user} - pivot={item} + pivot={item.pivot} + machineInfo={item.machineInfo} entreprises={entreprises.value} /> )} diff --git a/packages/ui/src/components/demarche/demarche-etape.stories.tsx b/packages/ui/src/components/demarche/demarche-etape.stories.tsx index fc40ce336..0a890add2 100644 --- a/packages/ui/src/components/demarche/demarche-etape.stories.tsx +++ b/packages/ui/src/components/demarche/demarche-etape.stories.tsx @@ -1,7 +1,7 @@ import { Meta, StoryFn } from '@storybook/vue3' import { DemarcheEtape } from './demarche-etape' import { EtapesTypesEtapesStatuts } from 'camino-common/src/static/etapesTypesEtapesStatuts' -import { toCaminoDate } from 'camino-common/src/date' +import { firstEtapeDateValidator, toCaminoDate } from 'camino-common/src/date' import { Entreprise, EtapeEntrepriseDocument, entrepriseDocumentIdValidator, entrepriseIdValidator } from 'camino-common/src/entreprise' import { titreSlugValidator } from 'camino-common/src/validators/titres' import { action } from '@storybook/addon-actions' @@ -19,6 +19,7 @@ import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' import { ETAPES_STATUTS } from 'camino-common/src/static/etapesStatuts' import { AVIS_STATUTS, AVIS_TYPES, AvisVisibilityIds } from 'camino-common/src/static/avisTypes' import { TitresStatutIds } from 'camino-common/src/static/titresStatuts' +import { MachineInfo } from 'camino-common/src/machines' import { TITRES_TYPES_IDS } from 'camino-common/src/static/titresTypes' import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes' @@ -290,14 +291,17 @@ const fondamentale: DemarcheEtapeFondamentale['fondamentale'] = { secteurs_maritimes: [], }, } +const demarcheId = demarcheIdValidator.parse('demarcheId') +const firstEtapeDate = firstEtapeDateValidator.parse('2020-01-01') export const NoSnapshotDemande: StoryFn = () => ( <DemarcheEtape - titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} + titre={{ titreStatutId: 'val', typeId: TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ - id: demarcheIdValidator.parse('demarcheId'), + id: demarcheId, + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_visibilite: 'Publique', - demarche_type_id: 'oct', + demarche_type_id: DEMARCHES_TYPES_IDS.Octroi, titulaireIds: [entrepriseIdValidator.parse('titulaire1'), entrepriseIdValidator.parse('titulaire2')], administrationsLocales: [], sdom_zones: [], @@ -334,7 +338,8 @@ export const DemandeMultipleEntreprisesDocuments: StoryFn = () => ( demarche={{ demarche_visibilite: 'Publique', demarche_type_id: 'oct', - id: demarcheIdValidator.parse('demarcheId'), + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), + id: demarcheId, demarche_statut_id: DemarchesStatutsIds.EnInstruction, titulaireIds: [entrepriseIdValidator.parse('titulaire1'), entrepriseIdValidator.parse('titulaire2')], administrationsLocales: [], @@ -417,7 +422,8 @@ export const DemandeNoMap: StoryFn = () => ( titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), + id: demarcheId, demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [entrepriseIdValidator.parse('titulaire1')], @@ -485,7 +491,8 @@ export const DemandeNonDeposable: StoryFn = () => ( titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + id: demarcheId, + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [], @@ -532,7 +539,8 @@ export const DemandeNonSupprimable: StoryFn = () => ( titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + id: demarcheId, + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [entrepriseIdValidator.parse('titulaire1')], @@ -617,8 +625,9 @@ export const DemandeArmMecaniseNonDeposable: StoryFn = () => ( <DemarcheEtape titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ + id: demarcheId, demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [entrepriseIdValidator.parse('titulaire1')], @@ -715,7 +724,8 @@ export const DemandeArmMecaniseDeposable: StoryFn = () => ( titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + id: demarcheId, + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [entrepriseIdValidator.parse('titulaire1')], @@ -816,7 +826,8 @@ export const DemandeArmNonMecaniseDeposable: StoryFn = () => ( titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + id: demarcheId, + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [entrepriseIdValidator.parse('titulaire1')], @@ -877,7 +888,8 @@ export const Depot: StoryFn = () => ( titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + id: demarcheId, + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [entrepriseIdValidator.parse('titulaire1')], @@ -912,7 +924,8 @@ export const AvisDefavorable: StoryFn = () => ( titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + id: demarcheId, + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [], @@ -966,7 +979,8 @@ export const DemandeAvecSeulementPerimetre: StoryFn = () => ( titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + id: demarcheId, + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [], @@ -1045,7 +1059,8 @@ export const DemandeAvecGrosseNote: StoryFn = () => ( titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + id: demarcheId, + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [], @@ -1106,7 +1121,8 @@ export const AxmDeposableAvecDaeEtAsl: StoryFn = () => ( titre={{ titreStatutId: 'dmi', typeId: 'axm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + id: demarcheId, + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [entrepriseIdValidator.parse('titulaire1')], @@ -1232,7 +1248,8 @@ export const DemandeAvecForage: StoryFn = () => ( titre={{ titreStatutId: 'val', typeId: 'pxg', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + id: demarcheId, + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.PERMIS_D_EXPLOITATION_GEOTHERMIE, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [], @@ -1303,7 +1320,8 @@ export const AvisDesServices: StoryFn = () => ( titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + id: demarcheId, + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [entrepriseIdValidator.parse('titulaire1')], @@ -1338,7 +1356,8 @@ export const AvisDesServicesSansTelechargerToutLesDocuments: StoryFn = () => ( titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + id: demarcheId, + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [entrepriseIdValidator.parse('titulaire1')], @@ -1392,7 +1411,8 @@ export const EtapeAvecNoteAvertissement: StoryFn = () => ( titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), + id: demarcheId, demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [entrepriseIdValidator.parse('titulaire1')], @@ -1426,8 +1446,9 @@ export const DemandeDeComplement: StoryFn = () => ( <DemarcheEtape titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ + id: demarcheId, demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [entrepriseIdValidator.parse('titulaire1')], @@ -1481,8 +1502,9 @@ export const DemandeDeConsentement: StoryFn = () => ( <DemarcheEtape titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ + id: demarcheId, demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [entrepriseIdValidator.parse('titulaire1')], @@ -1535,7 +1557,8 @@ export const DemandeDeComplementEntreprise: StoryFn = () => ( titre={{ titreStatutId: 'val', typeId: 'arm', nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + id: demarcheId, + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: 'oct', titulaireIds: [entrepriseIdValidator.parse('titulaire1')], @@ -1605,7 +1628,8 @@ export const EtapeSimple: StoryFn = () => ( titre={{ titreStatutId: TitresStatutIds.Valide, typeId: TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, nom: 'nom du titre', slug: titreSlug, titre_visibilite: 'Publique' }} demarche={{ demarche_visibilite: 'Publique', - id: demarcheIdValidator.parse('demarcheId'), + id: demarcheId, + machineInfo: MachineInfo.withDate(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, firstEtapeDate), demarche_statut_id: DemarchesStatutsIds.EnInstruction, demarche_type_id: DEMARCHES_TYPES_IDS.Octroi, titulaireIds: [entrepriseIdValidator.parse('titulaire1')], diff --git a/packages/ui/src/components/demarche/demarche-etape.tsx b/packages/ui/src/components/demarche/demarche-etape.tsx index 4201d4ef4..6257e9e3c 100644 --- a/packages/ui/src/components/demarche/demarche-etape.tsx +++ b/packages/ui/src/components/demarche/demarche-etape.tsx @@ -10,11 +10,11 @@ import { EtapeStatut } from '../_common/etape-statut' import { PropDuree } from '../etape/prop-duree' import { SubstancesLegale } from 'camino-common/src/static/substancesLegales' import { EtapePropEntreprisesItem, EtapePropItem } from '../etape/etape-prop-item' -import { DemarcheEtape as CommonDemarcheEtape, DemarcheConsentement, demarcheEnregistrementDemandeDateFind, DemarcheId } from 'camino-common/src/demarche' +import { DemarcheEtape as CommonDemarcheEtape, DemarcheConsentement, DemarcheId } from 'camino-common/src/demarche' import { DsfrPerimetre, TabId } from '../_common/dsfr-perimetre' import { TitreSlug } from 'camino-common/src/validators/titres' import { numberFormat } from 'camino-common/src/number' -import { OmitDistributive, getValues, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, isNullOrUndefined } from 'camino-common/src/typescript-tools' +import { OmitDistributive, getValues, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty } from 'camino-common/src/typescript-tools' import { ElementWithValue, valeurFind } from 'camino-common/src/sections' import { EtapeDocuments } from '../etape/etape-documents' import { isEntrepriseOrBureauDEtude, User } from 'camino-common/src/roles' @@ -50,6 +50,7 @@ import { LoadingElement } from '../_ui/functional-loader' import { useState } from '@/utils/vue-tsx-utils' import { fr } from '@codegouvfr/react-dsfr' import { EtapeVisibilite } from '../_common/etape-visibilite' +import { MachineInfo } from 'camino-common/src/machines' // Il ne faut pas utiliser de literal dans le 'in' il n'y aura jamais d'erreur typescript const fondamentalePropsName = 'fondamentale' @@ -65,6 +66,7 @@ type Props = { sdom_zones: SDOMZoneId[] communes: CommuneId[] etapes: TitreGetDemarche['etapes'] + machineInfo: MachineInfo } titre: { typeId: TitreTypeId @@ -157,7 +159,8 @@ export const DemarcheEtape = defineComponent<Props>(props => { const perimetre = getMostRecentValuePropFromEtapeFondamentale('perimetre', [{ ...props.demarche, ordre: 0 }]) const substances = getMostRecentValuePropFromEtapeFondamentale('substances', [{ ...props.demarche, ordre: 0 }]) const duree = getMostRecentValuePropFromEtapeFondamentale('duree', [{ ...props.demarche, ordre: 0 }]) - const sections = getSections(props.titre.typeId, props.demarche.demarche_type_id, props.etape.etape_type_id) + + const sections = getSections(props.demarche.machineInfo, props.etape.etape_type_id) const sortedEtapes = [...props.demarche.etapes].sort((a, b) => b.ordre - a.ordre) const contenu: FlattenEtape['contenu'] = {} @@ -179,16 +182,10 @@ export const DemarcheEtape = defineComponent<Props>(props => { }) }) - const firstEtapeDate = demarcheEnregistrementDemandeDateFind(props.demarche.etapes.map(({ date, etape_type_id }) => ({ date, typeId: etape_type_id }))) - if (isNullOrUndefined(firstEtapeDate)) { - return false - } - return canDeposeEtape( props.user, - { typeId: props.titre.typeId, titreStatutId: props.titre.titreStatutId, titulaires: props.demarche.titulaireIds, administrationsLocales: props.demarche.administrationsLocales }, - props.demarche.id, - props.demarche.demarche_type_id, + props.demarche.machineInfo, + { titreStatutId: props.titre.titreStatutId, titulaires: props.demarche.titulaireIds, administrationsLocales: props.demarche.administrationsLocales }, { amodiataires: { value: amodiataireIds ?? [], heritee: false, etapeHeritee: null }, titulaires: { value: titulaireIds ?? [], heritee: false, etapeHeritee: null }, @@ -219,8 +216,7 @@ export const DemarcheEtape = defineComponent<Props>(props => { props.etape.entreprises_documents, props.demarche.sdom_zones, props.demarche.communes, - props.etape.avis_documents, - firstEtapeDate + props.etape.avis_documents ) }) @@ -446,7 +442,7 @@ export const DemarcheEtape = defineComponent<Props>(props => { class="fr-pt-2w" initTab={props.initTab} titreSlug={props.titre.slug} - titreTypeId={props.titre.typeId} + machineInfo={props.demarche.machineInfo} id={props.etape.id} calculateNeighbours={false} perimetre={{ diff --git a/packages/ui/src/components/demarche/demarche-map.tsx b/packages/ui/src/components/demarche/demarche-map.tsx index d975cd418..5b6ea10e5 100644 --- a/packages/ui/src/components/demarche/demarche-map.tsx +++ b/packages/ui/src/components/demarche/demarche-map.tsx @@ -8,7 +8,7 @@ import { TitreApiClient } from '../titre/titre-api-client' import { TitreWithPerimetre } from '../titres/mapUtil' import { isNotNullNorUndefined, isNullOrUndefined } from 'camino-common/src/typescript-tools' import { couleurParDomaine } from '../_common/domaine' -import { TitreTypeId, getDomaineId } from 'camino-common/src/static/titresTypes' +import { getDomaineId } from 'camino-common/src/static/titresTypes' import { canHaveForages } from 'camino-common/src/permissions/titres' import { capitalize } from 'camino-common/src/strings' import { CaminoLngLatBounds, CaminoMapLibre, CaminoStyleSpecification } from '@/typings/maplibre-gl' @@ -32,6 +32,7 @@ import { titresValidesLineName, } from './demarche-map-layer-controls' import { CaminoRouter } from '@/typings/vue-router' +import { MachineInfo } from 'camino-common/src/machines' type Props = { id: string @@ -39,7 +40,7 @@ type Props = { maxMarkers: number style?: HTMLAttributes['style'] class?: HTMLAttributes['class'] - titreTypeId: TitreTypeId + machineInfo: MachineInfo neighbours: { apiClient: Pick<TitreApiClient, 'getTitresWithPerimetreForCarte'> titreSlug: TitreSlug @@ -253,7 +254,7 @@ export const DemarcheMap = defineComponent<Props>(props => { values.push('Points') } - if (canHaveForages(props.titreTypeId)) { + if (canHaveForages(props.machineInfo)) { values.push('Forages') } @@ -567,7 +568,7 @@ export const DemarcheMap = defineComponent<Props>(props => { if (isNullOrUndefined(props.neighbours) && name === 'Titres valides') { return false } - if (!canHaveForages(props.titreTypeId) && name === 'Forages') { + if (!canHaveForages(props.machineInfo) && name === 'Forages') { return false } @@ -589,4 +590,4 @@ export const DemarcheMap = defineComponent<Props>(props => { ) }) // @ts-ignore waiting for https://github.com/vuejs/core/issues/7833 -DemarcheMap.props = ['id', 'perimetre', 'class', 'style', 'maxMarkers', 'neighbours', 'router', 'titreTypeId'] +DemarcheMap.props = ['id', 'perimetre', 'class', 'style', 'maxMarkers', 'neighbours', 'router', 'machineInfo'] diff --git a/packages/ui/src/components/etape-edition.stories.tsx b/packages/ui/src/components/etape-edition.stories.tsx index f1740055a..9f2ff0106 100644 --- a/packages/ui/src/components/etape-edition.stories.tsx +++ b/packages/ui/src/components/etape-edition.stories.tsx @@ -284,6 +284,7 @@ const apiClient: Props['apiClient'] = { demarche_type_id: 'oct', demarche_description: 'Super description', demarche_id: demarcheId, + machine_id: 'AncienLogigrammeOctroiARM', titre_id: titreIdValidator.parse('titre-id'), titre_slug: titreSlugValidator.parse('titre-slug'), @@ -305,6 +306,7 @@ const apiClient: Props['apiClient'] = { titre_nom: 'Nom du titre', titre_slug: titreSlugValidator.parse('titre-slug'), titre_type_id: 'arm', + machine_id: null, first_etape_date: firstEtapeDateValidator.parse('2022-01-01'), }) }, @@ -396,6 +398,7 @@ export const AffichageAide: StoryFn = () => ( titre_nom: 'Nom du titre', titre_type_id: 'arm', first_etape_date: firstEtapeDateValidator.parse('2022-01-01'), + machine_id: 'AncienLogigrammeOctroiARM', }, }) }, @@ -582,6 +585,7 @@ export const DemandeArmComplete: StoryFn = () => ( heritageContenu: {}, }, demarche: { + machine_id: 'AncienLogigrammeOctroiARM', demarche_id: demarcheId, demarche_slug: demarcheSlugValidator.parse('demarche-slug'), demarche_type_id: 'oct', @@ -751,6 +755,7 @@ export const ModificationDemandeHeritee: StoryFn = () => ( }, }, demarche: { + machine_id: null, demarche_id: demarcheIdValidator.parse('demarche-id'), demarche_type_id: demarcheTypeIdValidator.parse('oct'), demarche_slug: demarcheSlugValidator.parse('demarche-slug'), @@ -875,6 +880,7 @@ export const AxmEnZoneDuSdom: StoryFn = () => ( heritageContenu: {}, }, demarche: { + machine_id: 'AncienLogigrammeOctroiAXM', demarche_id: demarcheIdValidator.parse('demarche-id'), demarche_type_id: demarcheTypeIdValidator.parse('oct'), demarche_slug: demarcheSlugValidator.parse('demarche-slug'), @@ -894,3 +900,26 @@ export const AxmEnZoneDuSdom: StoryFn = () => ( etapeIdOrSlug={etapeIdOrSlugValidator.parse('etape-id')} /> ) + +export const Loading: StoryFn = () => ( + <PureEtapeEdition + goToDemarche={goToDemarcheAction} + entreprises={entreprises} + apiClient={{ ...apiClient, getEtape: () => new Promise(() => ({})) }} + user={{ ...testBlankUser, role: 'super' }} + initTab="points" + demarcheIdOrSlug={null} + etapeIdOrSlug={etapeIdOrSlugValidator.parse('etape-id')} + /> +) +export const WithError: StoryFn = () => ( + <PureEtapeEdition + goToDemarche={goToDemarcheAction} + entreprises={entreprises} + apiClient={{ ...apiClient, getEtape: () => Promise.resolve({ message: 'Une erreur' }) }} + user={{ ...testBlankUser, role: 'super' }} + initTab="points" + demarcheIdOrSlug={null} + etapeIdOrSlug={etapeIdOrSlugValidator.parse('etape-id')} + /> +) diff --git a/packages/ui/src/components/etape-edition.stories_snapshots_Loading.html b/packages/ui/src/components/etape-edition.stories_snapshots_Loading.html new file mode 100644 index 000000000..e3387ed78 --- /dev/null +++ b/packages/ui/src/components/etape-edition.stories_snapshots_Loading.html @@ -0,0 +1,7 @@ +<div> + <div class="_top-level_3306d0" style="display: flex; justify-content: center;"> + <!----> + <!----> + <div class="_spinner_3306d0"></div> + </div> +</div> \ No newline at end of file diff --git a/packages/ui/src/components/etape-edition.stories_snapshots_WithError.html b/packages/ui/src/components/etape-edition.stories_snapshots_WithError.html new file mode 100644 index 000000000..e7848acc6 --- /dev/null +++ b/packages/ui/src/components/etape-edition.stories_snapshots_WithError.html @@ -0,0 +1,9 @@ +<div> + <div class="" style="display: flex; justify-content: center;"> + <!----> + <div class="fr-alert fr-alert--error fr-alert--sm" role="alert"> + <p>Une erreur</p> + </div> + <!----> + </div> +</div> \ No newline at end of file diff --git a/packages/ui/src/components/etape-edition.tsx b/packages/ui/src/components/etape-edition.tsx index 65b9cedd6..e4d089e64 100644 --- a/packages/ui/src/components/etape-edition.tsx +++ b/packages/ui/src/components/etape-edition.tsx @@ -20,6 +20,7 @@ import { capitalize } from 'camino-common/src/strings' import { EtapeEditForm, Props as EtapeEditFormProps } from './etape/etape-edit-form' import { TitreTypeId } from 'camino-common/src/static/titresTypes' import { CaminoAccessError } from './error' +import { MachineInfo } from 'camino-common/src/machines' export const EtapeEdition = defineComponent(() => { const router = useRouter() @@ -84,7 +85,7 @@ const helpVisible = (user: User, titreTypeId: TitreTypeId, etapeTypeId: EtapeTyp } export const PureEtapeEdition = defineComponent<Props>(props => { - const [asyncData, setAsyncData] = useState<AsyncData<{ etape: EtapeEditFormProps['etape']; demarche: GetDemarcheByIdOrSlug; perimetre: PerimetreInformations }>>({ + const [asyncData, setAsyncData] = useState<AsyncData<{ etape: EtapeEditFormProps['etape']; demarche: GetDemarcheByIdOrSlug; perimetre: PerimetreInformations; machineInfo: MachineInfo }>>({ status: 'LOADING', }) @@ -100,7 +101,12 @@ export const PureEtapeEdition = defineComponent<Props>(props => { if ('message' in perimetre) { setAsyncData({ status: 'NEW_ERROR', error: perimetre }) } else { - setAsyncData({ status: 'LOADED', value: { etape, demarche, perimetre } }) + const machineInfo = MachineInfo.withMachineId(demarche.titre_type_id, demarche.demarche_type_id, demarche.demarche_id, demarche.machine_id) + if (!machineInfo.valid) { + setAsyncData({ status: 'NEW_ERROR', error: { message: machineInfo.error } }) + } else { + setAsyncData({ status: 'LOADED', value: { etape, demarche, perimetre, machineInfo: machineInfo.value } }) + } } } } else if (isNotNullNorUndefined(props.demarcheIdOrSlug)) { @@ -112,31 +118,37 @@ export const PureEtapeEdition = defineComponent<Props>(props => { if ('message' in perimetre) { setAsyncData({ status: 'NEW_ERROR', error: perimetre }) } else { - setAsyncData({ - status: 'LOADED', - value: { - etape: { - id: null, - contenu: {}, - date: null, - typeId: null, - statutId: null, - isBrouillon: ETAPE_IS_NOT_BROUILLON, - note: { valeur: '', is_avertissement: false }, - substances: { value: [], heritee: true, etapeHeritee: null }, - titulaires: { value: [], heritee: true, etapeHeritee: null }, - amodiataires: { value: [], heritee: true, etapeHeritee: null }, - perimetre: { value: null, heritee: true, etapeHeritee: null }, - duree: { value: null, heritee: true, etapeHeritee: null }, - dateDebut: { value: null, heritee: true, etapeHeritee: null }, - dateFin: { value: null, heritee: true, etapeHeritee: null }, - slug: null, - titreDemarcheId: demarche.demarche_id, + const machineInfo = MachineInfo.withMachineId(demarche.titre_type_id, demarche.demarche_type_id, demarche.demarche_id, demarche.machine_id) + if (!machineInfo.valid) { + setAsyncData({ status: 'NEW_ERROR', error: { message: machineInfo.error } }) + } else { + setAsyncData({ + status: 'LOADED', + value: { + etape: { + id: null, + contenu: {}, + date: null, + typeId: null, + statutId: null, + isBrouillon: ETAPE_IS_NOT_BROUILLON, + note: { valeur: '', is_avertissement: false }, + substances: { value: [], heritee: true, etapeHeritee: null }, + titulaires: { value: [], heritee: true, etapeHeritee: null }, + amodiataires: { value: [], heritee: true, etapeHeritee: null }, + perimetre: { value: null, heritee: true, etapeHeritee: null }, + duree: { value: null, heritee: true, etapeHeritee: null }, + dateDebut: { value: null, heritee: true, etapeHeritee: null }, + dateFin: { value: null, heritee: true, etapeHeritee: null }, + slug: null, + titreDemarcheId: demarche.demarche_id, + }, + demarche, + perimetre, + machineInfo: machineInfo.value, }, - demarche, - perimetre, - }, - }) + }) + } } } } @@ -161,7 +173,7 @@ export const PureEtapeEdition = defineComponent<Props>(props => { <div> <LoadingElement data={asyncData.value} - renderItem={({ etape, demarche, perimetre }) => ( + renderItem={({ etape, demarche, perimetre, machineInfo }) => ( <> <div> <DsfrLink to={{ name: 'titre', params: { id: demarche.titre_slug } }} disabled={false} title={demarche.titre_nom} icon={null} /> @@ -198,11 +210,8 @@ export const PureEtapeEdition = defineComponent<Props>(props => { <EtapeEditForm initTab={props.initTab} etape={etape} - demarcheId={demarche.demarche_id} - demarcheTypeId={demarche.demarche_type_id} + machineInfo={machineInfo} titreSlug={demarche.titre_slug} - titreTypeId={demarche.titre_type_id} - firstEtapeDate={demarche.first_etape_date} user={props.user} entreprises={props.entreprises} apiClient={props.apiClient} diff --git a/packages/ui/src/components/etape/entreprises-documents-edit.stories.tsx b/packages/ui/src/components/etape/entreprises-documents-edit.stories.tsx index faddd92d3..21b141681 100644 --- a/packages/ui/src/components/etape/entreprises-documents-edit.stories.tsx +++ b/packages/ui/src/components/etape/entreprises-documents-edit.stories.tsx @@ -2,9 +2,11 @@ import { Meta, StoryFn } from '@storybook/vue3' import { EntrepriseDocumentsEdit } from './entreprises-documents-edit' import { action } from '@storybook/addon-actions' import { EntrepriseDocument, entrepriseDocumentIdValidator, newEntrepriseId, toEntrepriseDocumentId } from 'camino-common/src/entreprise' -import { toCaminoDate } from 'camino-common/src/date' +import { firstEtapeDateValidator, toCaminoDate } from 'camino-common/src/date' import { etapeIdValidator } from 'camino-common/src/etape' import { tempDocumentNameValidator } from 'camino-common/src/document' +import { MachineInfo } from 'camino-common/src/machines' +import { demarcheIdValidator } from 'camino-common/src/demarche' const meta: Meta = { title: 'Components/Etape/EditionEntreprisesDocuments', @@ -18,9 +20,11 @@ const getEntrepriseDocumentsAction = action('getEntrepriseDocuments') const completeUpdateAction = action('completeUpdate') const getEtapeEntrepriseDocumentsAction = action('getEtapeEntrepriseDocuments') const uploadTempDocumentAction = action('uploadTempDocumentAction') +const demarcheId = demarcheIdValidator.parse('demarcheId') +const firstEtapeDate = firstEtapeDateValidator.parse('2020-01-01') export const Loading: StoryFn = () => ( <EntrepriseDocumentsEdit - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'mfr' }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} apiClient={{ creerEntrepriseDocument: async (entrepriseId, entrepriseDocumentInput) => { creerEntrepriseDocumentAction(entrepriseId, entrepriseDocumentInput) @@ -48,7 +52,7 @@ export const Loading: StoryFn = () => ( export const ArmUneEntrepriseSansDocumentDEntreprise: StoryFn = () => ( <EntrepriseDocumentsEdit - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'mfr' }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} apiClient={{ creerEntrepriseDocument: async (entrepriseId, entrepriseDocumentInput) => { creerEntrepriseDocumentAction(entrepriseId, entrepriseDocumentInput) @@ -147,7 +151,7 @@ export const ArmUneEntrepriseSansDocumentDEntreprise: StoryFn = () => ( export const ArmUneEntrepriseAvecDocumentDEntrepriseComplet: StoryFn = () => ( <EntrepriseDocumentsEdit - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'mfr' }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} apiClient={{ creerEntrepriseDocument: async (entrepriseId, entrepriseDocumentInput) => { creerEntrepriseDocumentAction(entrepriseId, entrepriseDocumentInput) @@ -295,7 +299,7 @@ export const ArmUneEntrepriseAvecDocumentDEntrepriseComplet: StoryFn = () => ( export const AxmDeuxEntreprisesDocumentDEntrepriseComplet: StoryFn = () => ( <EntrepriseDocumentsEdit - tde={{ titreTypeId: 'axm', demarcheTypeId: 'oct', etapeTypeId: 'mfr' }} + tde={{ machineInfo: MachineInfo.withDate('axm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} apiClient={{ creerEntrepriseDocument: async (entrepriseId, entrepriseDocumentInput) => { creerEntrepriseDocumentAction(entrepriseId, entrepriseDocumentInput) @@ -450,7 +454,7 @@ export const AxmDeuxEntreprisesDocumentDEntrepriseComplet: StoryFn = () => ( export const ArmDocumentOptionnel: StoryFn = () => ( <EntrepriseDocumentsEdit - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'mod' }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mod' }} apiClient={{ creerEntrepriseDocument: async (entrepriseId, entrepriseDocumentInput) => { creerEntrepriseDocumentAction(entrepriseId, entrepriseDocumentInput) @@ -492,7 +496,7 @@ export const ArmDocumentOptionnel: StoryFn = () => ( export const ErreurDeChargementDesDocuments: StoryFn = () => ( <EntrepriseDocumentsEdit - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'mod' }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mod' }} apiClient={{ creerEntrepriseDocument: async (entrepriseId, entrepriseDocumentInput) => { creerEntrepriseDocumentAction(entrepriseId, entrepriseDocumentInput) diff --git a/packages/ui/src/components/etape/entreprises-documents-edit.tsx b/packages/ui/src/components/etape/entreprises-documents-edit.tsx index 4973f9c84..7f027036d 100644 --- a/packages/ui/src/components/etape/entreprises-documents-edit.tsx +++ b/packages/ui/src/components/etape/entreprises-documents-edit.tsx @@ -5,8 +5,6 @@ import { DocumentsTypes, EntrepriseDocumentType, EntrepriseDocumentTypeId } from import { getEntries, getEntriesHardcore, getKeys, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, isNullOrUndefined, map, stringArrayEquals } from 'camino-common/src/typescript-tools' import { AddEntrepriseDocumentPopup } from '../entreprise/add-entreprise-document-popup' import { AsyncData, getDownloadRestRoute } from '@/api/client-rest' -import { TitreTypeId } from 'camino-common/src/static/titresTypes' -import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' import { EtapeTypeId } from 'camino-common/src/static/etapesTypes' import { getEntrepriseDocuments } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/entrepriseDocuments' import { EtapeId } from 'camino-common/src/etape' @@ -19,13 +17,13 @@ import { SelectedEntrepriseDocument } from 'camino-common/src/permissions/etape- import { Column, TableSimple } from '../_ui/table-simple' import { TableRow } from '../_ui/table' import { fr } from '@codegouvfr/react-dsfr' +import { MachineInfo } from 'camino-common/src/machines' type Entreprise = { id: EntrepriseId; nom: string } interface Props { tde: { - titreTypeId: TitreTypeId - demarcheTypeId: DemarcheTypeId + machineInfo: MachineInfo etapeTypeId: EtapeTypeId } completeUpdate: (etapeEntrepriseDocuments: SelectedEntrepriseDocument[]) => void @@ -98,7 +96,7 @@ const InternalEntrepriseDocumentsEdit = defineComponent<Props & { etapeEntrepris }, {}) }) const tdeEntrepriseDocuments = computed<EntrepriseDocumentType[]>(() => { - return getEntrepriseDocuments(props.tde.titreTypeId, props.tde.demarcheTypeId, props.tde.etapeTypeId) + return getEntrepriseDocuments(props.tde.machineInfo, props.tde.etapeTypeId) }) const entrepriseDocuments = ref<AsyncData<{ [key in EntrepriseId]?: EntrepriseDocument[] }>>({ status: 'LOADING' }) diff --git a/packages/ui/src/components/etape/etape-api-client.ts b/packages/ui/src/components/etape/etape-api-client.ts index 7f4ab41a8..fccc8be9b 100644 --- a/packages/ui/src/components/etape/etape-api-client.ts +++ b/packages/ui/src/components/etape/etape-api-client.ts @@ -109,7 +109,6 @@ export const etapeApiClient: EtapeApiClient = { if ('message' in demarche) { return demarche } - return { etape, demarche } }, getEtapeHeritagePotentiel: async (etape, titreDemarcheId) => { diff --git a/packages/ui/src/components/etape/etape-avis-edit.stories.tsx b/packages/ui/src/components/etape/etape-avis-edit.stories.tsx index 0497e138b..16663f964 100644 --- a/packages/ui/src/components/etape/etape-avis-edit.stories.tsx +++ b/packages/ui/src/components/etape/etape-avis-edit.stories.tsx @@ -9,6 +9,7 @@ import { AvisVisibilityIds } from 'camino-common/src/static/avisTypes' import { testBlankUser } from 'camino-common/src/tests-utils' import { communeIdValidator } from 'camino-common/src/static/communes' import { demarcheIdValidator } from 'camino-common/src/demarche' +import { MachineInfo } from 'camino-common/src/machines' const meta: Meta = { title: 'Components/Etape/EtapeAvisEdit', @@ -56,13 +57,14 @@ const apiClient: Pick<ApiClient, 'uploadTempDocument' | 'getEtapeAvisByEtapeId'> } const completeUpdateAction = action('completeUpdate') - +const demarcheId = demarcheIdValidator.parse('demarcheId') +const firstEtapeDate = firstEtapeDateValidator.parse('2022-01-01') export const Empty: StoryFn = () => ( <EtapeAvisEdit apiClient={{ ...apiClient, getEtapeAvisByEtapeId: () => Promise.resolve([]) }} etapeId={etapeIdValidator.parse('etapeId')} communeIds={[]} - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'mfr', demarcheId: demarcheIdValidator.parse('demarcheId'), firstEtapeDate: firstEtapeDateValidator.parse('2022-01-01') }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} onChange={completeUpdateAction} user={{ ...testBlankUser, role: 'super' }} contenu={{}} @@ -73,7 +75,7 @@ export const Rempli: StoryFn = () => ( apiClient={apiClient} etapeId={etapeIdValidator.parse('etapeId')} communeIds={[]} - tde={{ titreTypeId: 'axm', demarcheTypeId: 'oct', etapeTypeId: 'asc', demarcheId: demarcheIdValidator.parse('demarcheId'), firstEtapeDate: firstEtapeDateValidator.parse('2022-01-01') }} + tde={{ machineInfo: MachineInfo.withDate('axm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'asc' }} onChange={completeUpdateAction} user={{ ...testBlankUser, role: 'super' }} contenu={{}} @@ -84,7 +86,7 @@ export const DemandeARMProcedureSpecifique: StoryFn = () => ( apiClient={apiClient} etapeId={etapeIdValidator.parse('etapeId')} communeIds={[]} - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'mfr', demarcheId: demarcheIdValidator.parse('demarcheId'), firstEtapeDate: firstEtapeDateValidator.parse('2025-01-01') }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDateValidator.parse('2025-01-01')), etapeTypeId: 'mfr' }} onChange={completeUpdateAction} user={{ ...testBlankUser, role: 'super' }} contenu={{ arm: { mecanise: { value: true, heritee: false, etapeHeritee: null } } }} @@ -111,7 +113,7 @@ export const AvisEnGuyane: StoryFn = () => ( }} etapeId={etapeIdValidator.parse('etapeId')} communeIds={[communeIdValidator.parse('97302')]} - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'asc', demarcheId: demarcheIdValidator.parse('demarcheId'), firstEtapeDate: firstEtapeDateValidator.parse('2022-01-01') }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'asc' }} onChange={completeUpdateAction} user={{ ...testBlankUser, role: 'super' }} contenu={{}} diff --git a/packages/ui/src/components/etape/etape-avis-edit.tsx b/packages/ui/src/components/etape/etape-avis-edit.tsx index ed976f763..8cc0c061a 100644 --- a/packages/ui/src/components/etape/etape-avis-edit.tsx +++ b/packages/ui/src/components/etape/etape-avis-edit.tsx @@ -1,7 +1,5 @@ import { EtapeAvis, EtapeAvisModification, EtapeId, TempEtapeAvis } from 'camino-common/src/etape' -import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' import { EtapeTypeId } from 'camino-common/src/static/etapesTypes' -import { TitreTypeId } from 'camino-common/src/static/titresTypes' import { ApiClient } from '../../api/api-client' import { FunctionalComponent, computed, defineComponent, onMounted, ref, watch } from 'vue' import { isNonEmptyArray, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, isNullOrUndefined, NonEmptyArray } from 'camino-common/src/typescript-tools' @@ -9,13 +7,12 @@ import { LoadingElement } from '../_ui/functional-loader' import { AsyncData, asyncDataAutomaticLoad } from '../../api/client-rest' import { DsfrButtonIcon } from '../_ui/dsfr-button' import { AddEtapeAvisPopup } from './add-etape-avis-popup' -import { dateFormat, FirstEtapeDate } from 'camino-common/src/date' +import { dateFormat } from 'camino-common/src/date' import { AvisStatut } from '../_common/etape-statut' import { AvisTypeId, getAvisNom } from 'camino-common/src/static/avisTypes' import { CommuneId } from 'camino-common/src/static/communes' import { getAvisVisibilityLabel } from './etape-avis' import { User } from 'camino-common/src/roles' -import { DemarcheId } from 'camino-common/src/demarche' import { FlattenedContenu } from 'camino-common/src/etape-form' import { capitalize } from 'camino-common/src/strings' import { fr } from '@codegouvfr/react-dsfr' @@ -24,14 +21,12 @@ import { TableRow } from '../_ui/table' import { getAvisTypes } from 'camino-common/src/avisTypes' import { isArmMecanise } from 'camino-common/src/static/mecanise' import { useState } from '@/utils/vue-tsx-utils' +import { MachineInfo } from 'camino-common/src/machines' interface Props { tde: { - titreTypeId: TitreTypeId - demarcheTypeId: DemarcheTypeId etapeTypeId: EtapeTypeId - demarcheId: DemarcheId - firstEtapeDate: FirstEtapeDate + machineInfo: MachineInfo } onChange: (etapeAvis: (EtapeAvis | TempEtapeAvis)[]) => void etapeId: EtapeId | null @@ -78,9 +73,7 @@ const EtapeAvisLoaded = defineComponent<EtapeAvisLoadedProps>(props => { const addOrEditPopupOpen = ref<{ open: true; required: boolean; avisTypeIds: NonEmptyArray<AvisTypeId>; etapeAvis?: (EtapeAvis | TempEtapeAvis) & WithIndex } | { open: false }>({ open: false }) const avisTypes = computed(() => { - return Object.values( - getAvisTypes(props.tde.etapeTypeId, props.tde.titreTypeId, props.tde.demarcheTypeId, props.tde.demarcheId, props.tde.firstEtapeDate, props.communeIds, isArmMecanise(props.contenu)) - ) + return Object.values(getAvisTypes(props.tde.etapeTypeId, props.tde.machineInfo, props.communeIds, isArmMecanise(props.contenu))) }) const completeRequiredAvis = computed<PropsTable['avis']>(() => { diff --git a/packages/ui/src/components/etape/etape-documents-edit.stories.tsx b/packages/ui/src/components/etape/etape-documents-edit.stories.tsx index 28c6969e7..a899fed96 100644 --- a/packages/ui/src/components/etape/etape-documents-edit.stories.tsx +++ b/packages/ui/src/components/etape/etape-documents-edit.stories.tsx @@ -9,6 +9,7 @@ import { useArgs } from '@storybook/preview-api' import { entrepriseIdValidator } from 'camino-common/src/entreprise' import { demarcheIdValidator } from 'camino-common/src/demarche' import { firstEtapeDateValidator } from 'camino-common/src/date' +import { MachineInfo } from 'camino-common/src/machines' const meta: Meta = { title: 'Components/Etape/EtapeDocumentsEdit', @@ -79,7 +80,7 @@ export const Empty: StoryFn = () => ( contenu={{}} etapeId={etapeIdValidator.parse('etapeId')} sdomZoneIds={[]} - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'mfr', demarcheId, firstEtapeDate }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} isBrouillon={ETAPE_IS_NOT_BROUILLON} completeUpdate={completeUpdateAction} user={{ ...testBlankUser, role: 'super' }} @@ -91,7 +92,7 @@ export const Rempli: StoryFn = () => ( contenu={{}} etapeId={etapeIdValidator.parse('etapeId')} sdomZoneIds={[]} - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'mfr', demarcheId, firstEtapeDate }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} isBrouillon={ETAPE_IS_NOT_BROUILLON} completeUpdate={completeUpdateAction} user={{ ...testBlankUser, role: 'super' }} @@ -151,7 +152,7 @@ export const Complet: StoryFn = () => ( contenu={{}} etapeId={etapeIdValidator.parse('etapeId')} sdomZoneIds={[]} - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'mfr', demarcheId, firstEtapeDate }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} isBrouillon={ETAPE_IS_NOT_BROUILLON} completeUpdate={completeUpdateAction} user={{ ...testBlankUser, role: 'super' }} @@ -211,7 +212,7 @@ export const CompletAvecDocumentNonRenseigne: StoryFn = () => ( contenu={{}} etapeId={etapeIdValidator.parse('etapeId')} sdomZoneIds={[]} - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'mfr', demarcheId, firstEtapeDate }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} isBrouillon={ETAPE_IS_NOT_BROUILLON} completeUpdate={completeUpdateAction} user={{ ...testBlankUser, role: 'super' }} @@ -224,7 +225,7 @@ export const ArmMecanise: StoryFn = () => ( contenu={{ arm: { mecanise: { value: true, heritee: false, etapeHeritee: null } } }} etapeId={etapeIdValidator.parse('etapeId')} sdomZoneIds={[]} - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'mfr', demarcheId, firstEtapeDate }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} isBrouillon={ETAPE_IS_NOT_BROUILLON} completeUpdate={completeUpdateAction} user={{ ...testBlankUser, role: 'admin', administrationId: 'dea-guyane-01' }} @@ -243,7 +244,7 @@ export const ArmMecaniseDynamicNoSnapshot: StoryObj<{ mecanise: boolean }> = { contenu={{ arm: { mecanise: { value: args.mecanise, heritee: false, etapeHeritee: null } } }} etapeId={etapeIdValidator.parse('etapeId')} sdomZoneIds={[]} - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'mfr', demarcheId, firstEtapeDate }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} isBrouillon={ETAPE_IS_NOT_BROUILLON} completeUpdate={completeUpdateAction} user={{ ...testBlankUser, role: 'super' }} @@ -262,7 +263,7 @@ export const EnConstruction: StoryFn = () => ( contenu={{ arm: { mecanise: { value: true, heritee: false, etapeHeritee: null } } }} etapeId={etapeIdValidator.parse('etapeId')} sdomZoneIds={[]} - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'mfr', demarcheId, firstEtapeDate }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} isBrouillon={ETAPE_IS_BROUILLON} completeUpdate={completeUpdateAction} user={{ ...testBlankUser, role: 'super' }} @@ -274,7 +275,7 @@ export const OctroiAxmUtilisateurSuper: StoryFn = () => ( contenu={{}} etapeId={etapeIdValidator.parse('etapeId')} sdomZoneIds={[]} - tde={{ titreTypeId: 'axm', demarcheTypeId: 'oct', etapeTypeId: 'mfr', demarcheId, firstEtapeDate }} + tde={{ machineInfo: MachineInfo.withDate('axm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} isBrouillon={ETAPE_IS_BROUILLON} completeUpdate={completeUpdateAction} user={{ ...testBlankUser, role: 'super' }} @@ -287,7 +288,7 @@ export const OctroiAxmUtilisateurEntreprise: StoryFn = () => ( contenu={{}} etapeId={etapeIdValidator.parse('etapeId')} sdomZoneIds={[]} - tde={{ titreTypeId: 'axm', demarcheTypeId: 'oct', etapeTypeId: 'mfr', demarcheId, firstEtapeDate }} + tde={{ machineInfo: MachineInfo.withDate('axm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} isBrouillon={ETAPE_IS_BROUILLON} completeUpdate={completeUpdateAction} user={{ ...testBlankUser, role: 'entreprise', entrepriseIds: [entrepriseIdValidator.parse('idEntreprise1')] }} @@ -350,7 +351,7 @@ export const OctroiAxmUtilisateurEntrepriseComplet: StoryFn = () => ( contenu={{}} etapeId={etapeIdValidator.parse('etapeId')} sdomZoneIds={[]} - tde={{ titreTypeId: 'axm', demarcheTypeId: 'oct', etapeTypeId: 'mfr', demarcheId, firstEtapeDate }} + tde={{ machineInfo: MachineInfo.withDate('axm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} isBrouillon={ETAPE_IS_BROUILLON} completeUpdate={completeUpdateAction} user={{ ...testBlankUser, role: 'entreprise', entrepriseIds: [entrepriseIdValidator.parse('idEntreprise1')] }} @@ -363,7 +364,7 @@ export const SdomZone: StoryFn = () => ( contenu={{ arm: { mecanise: { value: true, heritee: false, etapeHeritee: null } } }} etapeId={etapeIdValidator.parse('etapeId')} sdomZoneIds={['1', '2']} - tde={{ titreTypeId: 'axm', demarcheTypeId: 'oct', etapeTypeId: 'mfr', demarcheId, firstEtapeDate }} + tde={{ machineInfo: MachineInfo.withDate('axm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} isBrouillon={ETAPE_IS_NOT_BROUILLON} completeUpdate={completeUpdateAction} user={{ ...testBlankUser, role: 'super' }} @@ -376,7 +377,7 @@ export const PasDeDocumentsObligatoires: StoryFn = () => ( contenu={{}} etapeId={etapeIdValidator.parse('etapeId')} sdomZoneIds={['1', '2']} - tde={{ titreTypeId: 'prm', demarcheTypeId: 'pro', etapeTypeId: 'mfr', demarcheId, firstEtapeDate }} + tde={{ machineInfo: MachineInfo.withDate('prm', 'pro', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} isBrouillon={ETAPE_IS_NOT_BROUILLON} completeUpdate={completeUpdateAction} user={{ ...testBlankUser, role: 'super' }} @@ -389,7 +390,7 @@ export const Loading: StoryFn = () => ( contenu={{}} etapeId={etapeIdValidator.parse('etapeId')} sdomZoneIds={[]} - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'mfr', demarcheId, firstEtapeDate }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} isBrouillon={ETAPE_IS_NOT_BROUILLON} completeUpdate={completeUpdateAction} user={{ ...testBlankUser, role: 'super' }} @@ -401,7 +402,7 @@ export const WithError: StoryFn = () => ( contenu={{}} etapeId={etapeIdValidator.parse('etapeId')} sdomZoneIds={[]} - tde={{ titreTypeId: 'arm', demarcheTypeId: 'oct', etapeTypeId: 'mfr', demarcheId, firstEtapeDate }} + tde={{ machineInfo: MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate), etapeTypeId: 'mfr' }} isBrouillon={ETAPE_IS_NOT_BROUILLON} completeUpdate={completeUpdateAction} user={{ ...testBlankUser, role: 'super' }} diff --git a/packages/ui/src/components/etape/etape-documents-edit.tsx b/packages/ui/src/components/etape/etape-documents-edit.tsx index 8e973129d..e22275c94 100644 --- a/packages/ui/src/components/etape/etape-documents-edit.tsx +++ b/packages/ui/src/components/etape/etape-documents-edit.tsx @@ -1,7 +1,5 @@ import { EtapeBrouillon, EtapeDocument, EtapeDocumentModification, EtapeId, GetEtapeDocumentsByEtapeId, TempEtapeDocument } from 'camino-common/src/etape' -import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' import { EtapeTypeId } from 'camino-common/src/static/etapesTypes' -import { TitreTypeId } from 'camino-common/src/static/titresTypes' import { ApiClient } from '../../api/api-client' import { FunctionalComponent, computed, defineComponent, onMounted, ref, watch } from 'vue' import { SDOMZoneId } from 'camino-common/src/static/sdom' @@ -13,8 +11,6 @@ import { DsfrButtonIcon } from '../_ui/dsfr-button' import { getVisibilityLabel, sortDocumentsColumn } from './etape-documents' import { AddEtapeDocumentPopup } from './add-etape-document-popup' import { User } from 'camino-common/src/roles' -import { FirstEtapeDate } from 'camino-common/src/date' -import { DemarcheId } from 'camino-common/src/demarche' import { FlattenedContenu } from 'camino-common/src/etape-form' import { fr } from '@codegouvfr/react-dsfr' import { Column, TableSimple } from '../_ui/table-simple' @@ -22,14 +18,12 @@ import { TableRow } from '../_ui/table' import { getDocuments } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/documents' import { isArmMecanise } from 'camino-common/src/static/mecanise' import { useState } from '@/utils/vue-tsx-utils' +import { MachineInfo } from 'camino-common/src/machines' interface Props { tde: { - titreTypeId: TitreTypeId - demarcheTypeId: DemarcheTypeId etapeTypeId: EtapeTypeId - demarcheId: DemarcheId - firstEtapeDate: FirstEtapeDate + machineInfo: MachineInfo } isBrouillon: EtapeBrouillon sdomZoneIds: SDOMZoneId[] @@ -79,7 +73,7 @@ const EtapeDocumentsLoaded = defineComponent<EtapeDocumentsLoadedProps>(props => }) const documentTypes = computed<(DocumentType | AutreDocumentType)[]>(() => { - return getDocuments(props.tde.titreTypeId, props.tde.demarcheTypeId, props.tde.etapeTypeId, props.tde.firstEtapeDate, props.tde.demarcheId, props.sdomZoneIds, isArmMecanise(props.contenu)) + return getDocuments(props.tde.machineInfo, props.tde.etapeTypeId, props.sdomZoneIds, isArmMecanise(props.contenu)) }) const completeRequiredDocuments = computed<PropsTable['documents']>(() => { diff --git a/packages/ui/src/components/etape/etape-edit-form.stories.tsx b/packages/ui/src/components/etape/etape-edit-form.stories.tsx index 965a72cfe..3a83261a5 100644 --- a/packages/ui/src/components/etape/etape-edit-form.stories.tsx +++ b/packages/ui/src/components/etape/etape-edit-form.stories.tsx @@ -10,6 +10,7 @@ import { titreSlugValidator } from 'camino-common/src/validators/titres' import { FeatureMultiPolygon } from 'camino-common/src/perimetre' import { tempDocumentNameValidator } from 'camino-common/src/document' import { DOCUMENTS_TYPES_IDS } from 'camino-common/src/static/documentsTypes' +import { MachineInfo } from 'camino-common/src/machines' const meta: Meta = { title: 'Components/Etape/EditForm', @@ -231,16 +232,15 @@ const etapeEditFormApiClient: Props['apiClient'] = { return Promise.resolve({ id: entrepriseDocumentIdValidator.parse('entrepriseDocumentId') }) }, } - +const firstEtapeDate = firstEtapeDateValidator.parse('2022-01-01') +const demarcheId = demarcheIdValidator.parse('demarcheId') export const Default: StoryFn = () => ( <EtapeEditForm initTab="points" perimetre={{ sdomZoneIds: [], superposition_alertes: [], communes: [] }} apiClient={etapeEditFormApiClient} - demarcheId={demarcheIdValidator.parse('demarcheId')} - demarcheTypeId="oct" + machineInfo={MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate)} titreSlug={titreSlugValidator.parse('titre-slug')} - titreTypeId="arm" etape={{ ...etape, contenu: { arm: { mecanise: { value: true, heritee: false, etapeHeritee: null }, franchissements: { value: 2, heritee: false, etapeHeritee: null } } }, @@ -251,7 +251,6 @@ export const Default: StoryFn = () => ( }} entreprises={entreprises} goToDemarche={goToDemarcheAction} - firstEtapeDate={firstEtapeDateValidator.parse('2022-01-01')} /> ) @@ -412,10 +411,8 @@ export const EtapeCompleteEnregistrable: StoryFn = () => ( initTab="points" perimetre={{ sdomZoneIds: [], superposition_alertes: [], communes: [] }} apiClient={apiClientAvecDocumentsComplets} - demarcheId={demarcheIdValidator.parse('demarcheId')} - demarcheTypeId="oct" + machineInfo={MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate)} titreSlug={titreSlugValidator.parse('titre-slug')} - titreTypeId="arm" etape={{ ...etape, perimetre: { @@ -446,7 +443,6 @@ export const EtapeCompleteEnregistrable: StoryFn = () => ( }} entreprises={entreprises} goToDemarche={goToDemarcheAction} - firstEtapeDate={firstEtapeDateValidator.parse('2022-01-01')} /> ) @@ -505,10 +501,8 @@ export const EtapeCompleteEnregistrableAvecDocumentNonRenseigne: StoryFn = () => return Promise.resolve(values) }, }} - demarcheId={demarcheIdValidator.parse('demarcheId')} - demarcheTypeId="oct" + machineInfo={MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate)} titreSlug={titreSlugValidator.parse('titre-slug')} - titreTypeId="arm" etape={{ ...etape, perimetre: { @@ -539,7 +533,6 @@ export const EtapeCompleteEnregistrableAvecDocumentNonRenseigne: StoryFn = () => }} entreprises={entreprises} goToDemarche={goToDemarcheAction} - firstEtapeDate={firstEtapeDateValidator.parse('2022-01-01')} /> ) @@ -547,10 +540,8 @@ export const EtapeModification: StoryFn = () => ( <EtapeEditForm initTab="points" apiClient={etapeEditFormApiClient} - demarcheId={demarcheIdValidator.parse('demarcheId')} - demarcheTypeId="oct" + machineInfo={MachineInfo.withDate('cxw', 'oct', demarcheId, firstEtapeDate)} titreSlug={titreSlugValidator.parse('titre-slug')} - titreTypeId="cxw" perimetre={{ sdomZoneIds: [], superposition_alertes: [], communes: [] }} etape={{ ...etape, @@ -576,7 +567,6 @@ export const EtapeModification: StoryFn = () => ( }} entreprises={entreprises} goToDemarche={goToDemarcheAction} - firstEtapeDate={firstEtapeDateValidator.parse('2022-01-01')} /> ) @@ -584,10 +574,8 @@ export const EtapeModificationAvis: StoryFn = () => ( <EtapeEditForm initTab="points" apiClient={etapeEditFormApiClient} - demarcheId={demarcheIdValidator.parse('demarcheId')} - demarcheTypeId="oct" + machineInfo={MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate)} titreSlug={titreSlugValidator.parse('titre-slug')} - titreTypeId="arm" perimetre={{ sdomZoneIds: [], superposition_alertes: [], communes: [] }} etape={{ ...etape, @@ -600,17 +588,14 @@ export const EtapeModificationAvis: StoryFn = () => ( }} entreprises={entreprises} goToDemarche={goToDemarcheAction} - firstEtapeDate={firstEtapeDateValidator.parse('2022-01-01')} /> ) export const EtapeDecisionAdministration: StoryFn = () => ( <EtapeEditForm initTab="points" apiClient={etapeEditFormApiClient} - demarcheId={demarcheIdValidator.parse('demarcheId')} - demarcheTypeId="oct" + machineInfo={MachineInfo.withDate('cxw', 'oct', demarcheId, firstEtapeDate)} titreSlug={titreSlugValidator.parse('titre-slug')} - titreTypeId="cxw" perimetre={{ sdomZoneIds: [], superposition_alertes: [], communes: [] }} etape={{ ...etape, @@ -625,17 +610,14 @@ export const EtapeDecisionAdministration: StoryFn = () => ( }} entreprises={entreprises} goToDemarche={goToDemarcheAction} - firstEtapeDate={firstEtapeDateValidator.parse('2022-01-01')} /> ) export const EtapeConsultationAdministrationsCentrales: StoryFn = () => ( <EtapeEditForm initTab="points" apiClient={etapeEditFormApiClient} - demarcheId={demarcheIdValidator.parse('demarcheId')} - demarcheTypeId="oct" + machineInfo={MachineInfo.withDate('cxw', 'oct', demarcheId, firstEtapeDate)} titreSlug={titreSlugValidator.parse('titre-slug')} - titreTypeId="cxw" perimetre={{ sdomZoneIds: [], superposition_alertes: [], communes: [] }} etape={{ ...etape, @@ -649,6 +631,5 @@ export const EtapeConsultationAdministrationsCentrales: StoryFn = () => ( }} entreprises={entreprises} goToDemarche={goToDemarcheAction} - firstEtapeDate={firstEtapeDateValidator.parse('2022-01-01')} /> ) diff --git a/packages/ui/src/components/etape/etape-edit-form.tsx b/packages/ui/src/components/etape/etape-edit-form.tsx index 9ce7e8bde..74955faca 100644 --- a/packages/ui/src/components/etape/etape-edit-form.tsx +++ b/packages/ui/src/components/etape/etape-edit-form.tsx @@ -7,8 +7,7 @@ import { EtapeDocumentsEdit } from './etape-documents-edit' import { ApiClient } from '../../api/api-client' import { User } from 'camino-common/src/roles' import { ETAPE_IS_NOT_BROUILLON, EtapeAvis, EtapeDocument, EtapeId, TempEtapeAvis, TempEtapeDocument } from 'camino-common/src/etape' -import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' -import { TitreTypeId } from 'camino-common/src/static/titresTypes' +import { TITRES_TYPES_IDS } from 'camino-common/src/static/titresTypes' import { TitreSlug } from 'camino-common/src/validators/titres' import { SDOMZoneIds, SDOMZones } from 'camino-common/src/static/sdom' import { Nullable, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty } from 'camino-common/src/typescript-tools' @@ -39,30 +38,28 @@ import { import { EtapeAlerte, PureFormSaveBtn } from './pure-form-save-btn' import { TitresStatuts } from 'camino-common/src/static/titresStatuts' import { EtapeAvisEdit } from './etape-avis-edit' -import { EtapeTypeId, canBeBrouillon } from 'camino-common/src/static/etapesTypes' +import { ETAPES_TYPES, EtapeTypeId, canBeBrouillon } from 'camino-common/src/static/etapesTypes' import { CoreEtapeCreationOrModification, GetEtapeHeritagePotentiel } from './etape-api-client' import { FlattenedContenuElement, FlattenEtape, RestEtapeCreation } from 'camino-common/src/etape-form' import { AsyncData } from '@/api/client-rest' -import { CaminoDate, FirstEtapeDate, firstEtapeDateValidator } from 'camino-common/src/date' +import { CaminoDate, firstEtapeDateValidator, getCurrent } from 'camino-common/src/date' import { EtapeStatutId } from 'camino-common/src/static/etapesStatuts' import { LoadingElement } from '../_ui/functional-loader' import { isEtapeComplete, isEtapeDeposable, isEtapeValid } from 'camino-common/src/permissions/titres-etapes' import { getSections } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/sections' import { DsfrInputCheckbox } from '../_ui/dsfr-input-checkbox' import { CaminoError } from 'camino-common/src/zod-tools' +import { MachineInfo } from 'camino-common/src/machines' export type Props = { etape: Pick<Nullable<FlattenEtape>, 'id' | 'date' | 'typeId' | 'statutId' | 'slug'> & Omit<FlattenEtape, 'date' | 'typeId' | 'statutId' | 'id' | 'slug'> - demarcheId: DemarcheId - demarcheTypeId: DemarcheTypeId - titreTypeId: TitreTypeId + machineInfo: MachineInfo titreSlug: TitreSlug user: User entreprises: Entreprise[] perimetre: PerimetreInformations initTab?: 'points' | 'carte' goToDemarche: (demarcheId: DemarcheId) => void - firstEtapeDate: FirstEtapeDate | null apiClient: Pick< ApiClient, | 'getEntrepriseDocuments' @@ -86,13 +83,8 @@ type EtapeDocumentEdit = (EtapeDocument | TempEtapeDocument)[] type EntrepriseDocumentEdit = SelectedEntrepriseDocument[] type EtapeAvisEdit = (EtapeAvis | TempEtapeAvis)[] -const mergeFlattenEtapeWithNewHeritage = ( - etape: CoreEtapeCreationOrModification, - titreTypeId: TitreTypeId, - demarcheTypeId: DemarcheTypeId, - heritageData: GetEtapeHeritagePotentiel -): CoreEtapeCreationOrModification => { - const sections = getSections(titreTypeId, demarcheTypeId, etape.typeId) +const mergeFlattenEtapeWithNewHeritage = (etape: CoreEtapeCreationOrModification, machineInfo: MachineInfo, heritageData: GetEtapeHeritagePotentiel): CoreEtapeCreationOrModification => { + const sections = getSections(machineInfo, etape.typeId) const flattenEtape: CoreEtapeCreationOrModification = { ...etape, contenu: sections.reduce<FlattenEtape['contenu']>((accSection, section) => { @@ -237,8 +229,8 @@ export const EtapeEditForm = defineComponent<Props>(props => { statutId, isBrouillon: isNotNullNorUndefined(currentEtape.id) ? currentEtape.isBrouillon : canBeBrouillon(typeId), } - const value = await props.apiClient.getEtapeHeritagePotentiel(etape, props.demarcheId) - setEtape({ status: 'LOADED', value: mergeFlattenEtapeWithNewHeritage(etape, props.titreTypeId, props.demarcheTypeId, value) }) + const value = await props.apiClient.getEtapeHeritagePotentiel(etape, props.machineInfo.demarcheId) + setEtape({ status: 'LOADED', value: mergeFlattenEtapeWithNewHeritage(etape, props.machineInfo, value) }) } catch (e: any) { console.error('error', e) setEtape({ @@ -271,7 +263,12 @@ export const EtapeEditForm = defineComponent<Props>(props => { } // si c’est une demande d’AXM, on doit afficher une alerte si on est en zone 0 ou 1 du Sdom - if (etape.value.status === 'LOADED' && isNotNullNorUndefined(etape.value.value) && ['mfr', 'mcr'].includes(etape.value.value.typeId) && props.titreTypeId === 'axm') { + if ( + etape.value.status === 'LOADED' && + isNotNullNorUndefined(etape.value.value) && + [ETAPES_TYPES.demande, ETAPES_TYPES.recevabiliteDeLaDemande].includes(etape.value.value.typeId) && + props.machineInfo.titreTypeId === TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX + ) { const zoneId = perimetreInfos.value.sdomZoneIds.find(id => [SDOMZoneIds.Zone0, SDOMZoneIds.Zone0Potentielle, SDOMZoneIds.Zone1].includes(id)) if (zoneId) { alertes.push({ message: `Le périmètre renseigné est dans une zone du Sdom interdite à l’exploitation minière : ${SDOMZones[zoneId].nom}` }) @@ -282,9 +279,25 @@ export const EtapeEditForm = defineComponent<Props>(props => { return alertes }) + const machineInfo = computed(() => { + if (isNotNullNorUndefined(props.machineInfo.machineId)) { + return props.machineInfo + } else { + if (etape.value.status === 'LOADED') { + return MachineInfo.withDate( + props.machineInfo.titreTypeId, + props.machineInfo.demarcheTypeId, + props.machineInfo.demarcheId, + firstEtapeDateValidator.parse(etape.value.value?.date ?? getCurrent()) + ) + } else { + return MachineInfo.withDate(props.machineInfo.titreTypeId, props.machineInfo.demarcheTypeId, props.machineInfo.demarcheId, firstEtapeDateValidator.parse(getCurrent())) + } + } + }) const canSave = computed<boolean>(() => { if (etape.value.status === 'LOADED' && isNotNullNorUndefined(etape.value.value)) { - const etapeValid = isEtapeValid(etape.value.value, props.titreTypeId, props.demarcheTypeId, props.demarcheId, props.firstEtapeDate ?? firstEtapeDateValidator.parse(etape.value.value.date)) + const etapeValid = isEtapeValid(etape.value.value, machineInfo.value) if (!etapeValid.valid) { return false } @@ -292,16 +305,13 @@ export const EtapeEditForm = defineComponent<Props>(props => { if (etape.value.value.isBrouillon === ETAPE_IS_NOT_BROUILLON) { const { valid } = isEtapeComplete( etape.value.value, - props.titreTypeId, - props.demarcheId, - props.demarcheTypeId, + machineInfo.value, etapeDocuments.value, entrepriseDocuments.value.map(e => ({ entreprise_document_type_id: e.documentTypeId, entreprise_id: e.entrepriseId })), props.perimetre.sdomZoneIds, props.perimetre.communes, etapeAvis.value, - props.user, - props.firstEtapeDate ?? firstEtapeDateValidator.parse(etape.value.value.date) + props.user ) return valid } @@ -314,16 +324,13 @@ export const EtapeEditForm = defineComponent<Props>(props => { if (etape.value.status === 'LOADED' && isNotNullNorUndefined(etape.value.value)) { return isEtapeDeposable( props.user, - props.titreTypeId, - props.demarcheId, - props.demarcheTypeId, + machineInfo.value, etape.value.value, etapeDocuments.value, entrepriseDocuments.value.map(({ documentTypeId, entrepriseId }) => ({ entreprise_document_type_id: documentTypeId, entreprise_id: entrepriseId })), props.perimetre.sdomZoneIds, props.perimetre.communes, - etapeAvis.value, - props.firstEtapeDate ?? firstEtapeDateValidator.parse(etape.value.value.date) + etapeAvis.value ) } @@ -382,7 +389,7 @@ export const EtapeEditForm = defineComponent<Props>(props => { etapeId = await props.apiClient.etapeModifier({ ...etape.value.value, id: props.etape.id, - titreDemarcheId: props.demarcheId, + titreDemarcheId: props.machineInfo.demarcheId, etapeAvis: etapeAvis.value, etapeDocuments: etapeDocuments.value, entrepriseDocumentIds: entrepriseDocuments.value.map(({ id }) => id), @@ -391,7 +398,7 @@ export const EtapeEditForm = defineComponent<Props>(props => { } else { etapeId = await props.apiClient.etapeCreer({ ...etape.value.value, - titreDemarcheId: props.demarcheId, + titreDemarcheId: props.machineInfo.demarcheId, etapeAvis: etapeAvis.value, etapeDocuments: etapeDocuments.value.filter(value => 'temp_document_name' in value), entrepriseDocumentIds: entrepriseDocuments.value.map(({ id }) => id), @@ -408,7 +415,7 @@ export const EtapeEditForm = defineComponent<Props>(props => { const saveAndReroute = async () => { const etapeId = await save() if (isNotNullNorUndefined(etapeId) && !('message' in etapeId)) { - props.goToDemarche(props.demarcheId) + props.goToDemarche(props.machineInfo.demarcheId) } return etapeId } @@ -425,7 +432,7 @@ export const EtapeEditForm = defineComponent<Props>(props => { return value } - props.goToDemarche(props.demarcheId) + props.goToDemarche(props.machineInfo.demarcheId) } return { message: "L'étape ne peut pas être sauvegardée" } @@ -449,7 +456,7 @@ export const EtapeEditForm = defineComponent<Props>(props => { ).valid } > - <DateTypeEdit etape={props.etape} apiClient={props.apiClient} completeUpdate={dateTypeCompleteUpdate} demarcheId={props.demarcheId} /> + <DateTypeEdit etape={props.etape} apiClient={props.apiClient} completeUpdate={dateTypeCompleteUpdate} demarcheId={props.machineInfo.demarcheId} /> </Bloc> ) : null} <LoadingElement @@ -460,6 +467,7 @@ export const EtapeEditForm = defineComponent<Props>(props => { <> <EtapeEditFormInternal {...props} + machineInfo={machineInfo.value} perimetre={perimetreInfos.value} etape={etapeLoaded} setEtape={setEtapeInternal} @@ -502,16 +510,13 @@ const EtapeEditFormInternal = defineComponent< setEntrepriseDocuments: (values: EntrepriseDocumentEdit) => void setEtapeAvis: (values: EtapeAvisEdit) => void alertesUpdate: (alertes: PerimetreInformations) => void + machineInfo: MachineInfo } & Omit<Props, 'etape'> >(props => { const documentsCompleteUpdate = (etapeDocuments: (EtapeDocument | TempEtapeDocument)[]) => { props.setEtapeDocuments(etapeDocuments) } - const firstEtapeDate = computed<FirstEtapeDate>(() => { - return props.firstEtapeDate ?? firstEtapeDateValidator.parse(props.etape.date) - }) - const avisCompleteUpdate = (etapeAvis: (EtapeAvis | TempEtapeAvis)[]) => { props.setEtapeAvis(etapeAvis) } @@ -578,43 +583,36 @@ const EtapeEditFormInternal = defineComponent< }) const isHelpVisible = computed<boolean>(() => { - return props.etape.typeId === 'mfr' && ['arm', 'axm'].includes(props.titreTypeId) + return ( + props.etape.typeId === ETAPES_TYPES.demande && [TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, TITRES_TYPES_IDS.AUTORISATION_D_EXPLOITATION_METAUX].includes(props.machineInfo.titreTypeId) + ) }) return () => ( <div> {fondamentaleStepIsVisible(props.etape.typeId) ? ( - <Bloc step={{ name: 'Propriétés', help: null }} complete={fondamentaleStepIsComplete(props.etape, props.demarcheTypeId, props.titreTypeId, props.user).valid}> - <FondamentalesEdit - etape={props.etape} - demarcheTypeId={props.demarcheTypeId} - titreTypeId={props.titreTypeId} - user={props.user} - entreprises={props.entreprises} - completeUpdate={fondamentalesCompleteUpdate} - firstEtapeDate={firstEtapeDate.value} - /> + <Bloc step={{ name: 'Propriétés', help: null }} complete={fondamentaleStepIsComplete(props.etape, props.machineInfo, props.user).valid}> + <FondamentalesEdit etape={props.etape} machineInfo={props.machineInfo} user={props.user} entreprises={props.entreprises} completeUpdate={fondamentalesCompleteUpdate} /> </Bloc> ) : null} - {sectionsStepIsVisible(props.etape, props.demarcheTypeId, props.titreTypeId) ? ( + {sectionsStepIsVisible(props.etape, props.machineInfo) ? ( <Bloc step={{ name: 'Propriétés spécifiques', help: isHelpVisible.value ? 'Ce bloc permet de savoir si la prospection est mécanisée ou non et s’il y a des franchissements de cours d’eau (si oui, combien ?)' : null, }} - complete={sectionsStepIsComplete(props.etape, props.demarcheTypeId, props.titreTypeId).valid} + complete={sectionsStepIsComplete(props.etape, props.machineInfo).valid} > - <SectionsEdit etape={props.etape} titreTypeId={props.titreTypeId} demarcheTypeId={props.demarcheTypeId} completeUpdate={sectionCompleteUpdate} /> + <SectionsEdit etape={props.etape} machineInfo={props.machineInfo} completeUpdate={sectionCompleteUpdate} /> </Bloc> ) : null} - {perimetreStepIsVisible(props.etape, props.demarcheTypeId) ? ( - <Bloc step={{ name: 'Périmètre', help: null }} complete={perimetreStepIsComplete(props.etape, props.demarcheTypeId).valid}> + {perimetreStepIsVisible(props.etape, props.machineInfo) ? ( + <Bloc step={{ name: 'Périmètre', help: null }} complete={perimetreStepIsComplete(props.etape, props.machineInfo).valid}> <PerimetreEdit etape={props.etape} - titreTypeId={props.titreTypeId} - demarcheTypeId={props.demarcheTypeId} + machineInfo={props.machineInfo} titreSlug={props.titreSlug} apiClient={props.apiClient} initTab={props.initTab} @@ -622,24 +620,17 @@ const EtapeEditFormInternal = defineComponent< onPointsChange={onEtapePointsChange} onForagesChange={onEtapeForagesChange} onHeritageChange={onEtapePerimetreHeritageChange} - firstEtapeDate={firstEtapeDate.value} /> </Bloc> ) : null} {etapeDocumentsStepIsVisible() ? ( - <Bloc - step={{ name: 'Liste des documents', help: null }} - complete={etapeDocumentsStepIsComplete(props.etape, props.demarcheTypeId, props.titreTypeId, props.demarcheId, props.etapeDocuments, props.perimetre.sdomZoneIds, firstEtapeDate.value).valid} - > + <Bloc step={{ name: 'Liste des documents', help: null }} complete={etapeDocumentsStepIsComplete(props.etape, props.machineInfo, props.etapeDocuments, props.perimetre.sdomZoneIds).valid}> <EtapeDocumentsEdit apiClient={props.apiClient} tde={{ - titreTypeId: props.titreTypeId, - demarcheTypeId: props.demarcheTypeId, + machineInfo: props.machineInfo, etapeTypeId: props.etape.typeId, - demarcheId: props.demarcheId, - firstEtapeDate: firstEtapeDate.value, }} etapeId={props.etape.id} completeUpdate={documentsCompleteUpdate} @@ -651,19 +642,13 @@ const EtapeEditFormInternal = defineComponent< </Bloc> ) : null} - {etapeAvisStepIsVisible(props.etape, props.titreTypeId, props.demarcheTypeId, props.demarcheId, firstEtapeDate.value, props.perimetre.communes) ? ( - <Bloc - step={{ name: 'Liste des avis', help: null }} - complete={etapeAvisStepIsComplete(props.etape, props.etapeAvis, props.titreTypeId, props.demarcheTypeId, props.demarcheId, firstEtapeDate.value, props.perimetre.communes).valid} - > + {etapeAvisStepIsVisible(props.etape, props.machineInfo, props.perimetre.communes) ? ( + <Bloc step={{ name: 'Liste des avis', help: null }} complete={etapeAvisStepIsComplete(props.etape, props.etapeAvis, props.machineInfo, props.perimetre.communes).valid}> <EtapeAvisEdit apiClient={props.apiClient} tde={{ - titreTypeId: props.titreTypeId, - demarcheTypeId: props.demarcheTypeId, + machineInfo: props.machineInfo, etapeTypeId: props.etape.typeId, - demarcheId: props.demarcheId, - firstEtapeDate: firstEtapeDate.value, }} etapeId={props.etape.id} contenu={props.etape.contenu} @@ -674,7 +659,7 @@ const EtapeEditFormInternal = defineComponent< </Bloc> ) : null} - {entrepriseDocumentsStepIsVisible(props.etape, props.demarcheTypeId, props.titreTypeId) ? ( + {entrepriseDocumentsStepIsVisible(props.etape, props.machineInfo) ? ( <Bloc step={{ name: 'Documents d’entreprise', @@ -683,12 +668,12 @@ const EtapeEditFormInternal = defineComponent< ? "Les documents d’entreprise sont des documents propres à l'entreprise, et pourront être réutilisés pour la création d'un autre dossier et mis à jour si nécessaire. Ces documents d’entreprise sont consultables dans la fiche entreprise de votre société. Cette section permet de protéger et de centraliser les informations d'ordre privé relatives à la société et à son personnel." : null, }} - complete={entrepriseDocumentsStepIsComplete(props.etape, props.demarcheTypeId, props.titreTypeId, props.entrepriseDocuments).valid} + complete={entrepriseDocumentsStepIsComplete(props.etape, props.machineInfo, props.entrepriseDocuments).valid} > <EntrepriseDocumentsEdit entreprises={titulairesAndAmodiataires.value} apiClient={props.apiClient} - tde={{ titreTypeId: props.titreTypeId, demarcheTypeId: props.demarcheTypeId, etapeTypeId: props.etape.typeId }} + tde={{ machineInfo: props.machineInfo, etapeTypeId: props.etape.typeId }} etapeId={props.etape.id} completeUpdate={entrepriseDocumentsCompleteUpdate} /> @@ -707,13 +692,11 @@ const EtapeEditFormInternal = defineComponent< }) // @ts-ignore waiting for https://github.com/vuejs/core/issues/7833 -EtapeEditForm.props = ['etape', 'demarcheId', 'demarcheTypeId', 'titreTypeId', 'titreSlug', 'user', 'perimetre', 'entreprises', 'apiClient', 'initTab', 'goToDemarche', 'firstEtapeDate'] +EtapeEditForm.props = ['etape', 'titreSlug', 'user', 'perimetre', 'entreprises', 'apiClient', 'initTab', 'goToDemarche', 'machineInfo'] // @ts-ignore waiting for https://github.com/vuejs/core/issues/7833 EtapeEditFormInternal.props = [ 'etape', - 'demarcheId', - 'demarcheTypeId', 'etapeDocuments', 'entrepriseDocuments', 'etapeAvis', @@ -721,7 +704,6 @@ EtapeEditFormInternal.props = [ 'setEtapeDocuments', 'setEntrepriseDocuments', 'setEtapeAvis', - 'titreTypeId', 'titreSlug', 'user', 'perimetre', @@ -731,5 +713,5 @@ EtapeEditFormInternal.props = [ 'initTab', 'setEtape', 'documents', - 'firstEtapeDate', + 'machineInfo', ] diff --git a/packages/ui/src/components/etape/fondamentales-edit.stories.tsx b/packages/ui/src/components/etape/fondamentales-edit.stories.tsx index 9e4cfdab9..bc29f4ca2 100644 --- a/packages/ui/src/components/etape/fondamentales-edit.stories.tsx +++ b/packages/ui/src/components/etape/fondamentales-edit.stories.tsx @@ -7,7 +7,7 @@ import { testBlankUser } from 'camino-common/src/tests-utils' import { action } from '@storybook/addon-actions' import { FlattenEtape } from 'camino-common/src/etape-form' import { demarcheIdValidator } from 'camino-common/src/demarche' -import { DATE_DEBUT_PROCEDURE_SPECIFIQUE } from 'camino-common/src/machines' +import { DATE_DEBUT_PROCEDURE_SPECIFIQUE, MachineInfo } from 'camino-common/src/machines' const meta: Meta = { title: 'Components/Etape/FondamentalesEdit', @@ -88,19 +88,18 @@ const entreprises = [ const completeUpdate = action('completeUpdate') const firstEtapeDate = firstEtapeDateValidator.parse('2022-01-01') +const demarcheId = demarcheIdValidator.parse('demarcheId') export const AxmDemandeSuper: StoryFn = () => ( <FondamentalesEdit etape={etape} completeUpdate={completeUpdate} - demarcheTypeId="oct" - titreTypeId="axm" + machineInfo={MachineInfo.withDate('axm', 'oct', demarcheId, firstEtapeDate)} user={{ role: 'super', ...testBlankUser, }} entreprises={entreprises} - firstEtapeDate={firstEtapeDate} /> ) @@ -108,15 +107,13 @@ export const ArmDemandeONF: StoryFn = () => ( <FondamentalesEdit etape={etape} completeUpdate={completeUpdate} - demarcheTypeId="oct" - titreTypeId="arm" + machineInfo={MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate)} user={{ role: 'admin', administrationId: 'ope-onf-973-01', ...testBlankUser, }} entreprises={entreprises} - firstEtapeDate={firstEtapeDate} /> ) @@ -124,11 +121,9 @@ export const ArmDemandeOperateur: StoryFn = () => ( <FondamentalesEdit etape={etape} completeUpdate={completeUpdate} - demarcheTypeId="oct" - titreTypeId="arm" + machineInfo={MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate)} user={{ role: 'entreprise', entrepriseIds: [], ...testBlankUser }} entreprises={entreprises} - firstEtapeDate={firstEtapeDate} /> ) @@ -136,11 +131,9 @@ export const ArmJorfONF: StoryFn = () => ( <FondamentalesEdit etape={{ ...etape, typeId: 'dpu' }} completeUpdate={completeUpdate} - demarcheTypeId="oct" - titreTypeId="arm" + machineInfo={MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate)} user={{ role: 'admin', administrationId: 'ope-onf-973-01', ...testBlankUser }} entreprises={entreprises} - firstEtapeDate={firstEtapeDate} /> ) @@ -148,11 +141,9 @@ export const AxmDemandeONF: StoryFn = () => ( <FondamentalesEdit etape={etape} completeUpdate={completeUpdate} - demarcheTypeId="oct" - titreTypeId="axm" + machineInfo={MachineInfo.withDate('axm', 'oct', demarcheId, firstEtapeDate)} user={{ role: 'admin', administrationId: 'ope-onf-973-01', ...testBlankUser }} entreprises={entreprises} - firstEtapeDate={firstEtapeDate} /> ) @@ -160,11 +151,9 @@ export const AxmDemandeTropLongue: StoryFn = () => ( <FondamentalesEdit etape={{ ...etape, date: DATE_DEBUT_PROCEDURE_SPECIFIQUE, duree: { value: 120, heritee: false, etapeHeritee: null } }} completeUpdate={completeUpdate} - demarcheTypeId="oct" - titreTypeId="axm" + machineInfo={MachineInfo.withDate('axm', 'oct', demarcheId, firstEtapeDateValidator.parse(DATE_DEBUT_PROCEDURE_SPECIFIQUE))} user={{ role: 'super', ...testBlankUser }} entreprises={entreprises} - firstEtapeDate={firstEtapeDateValidator.parse(DATE_DEBUT_PROCEDURE_SPECIFIQUE)} /> ) @@ -172,11 +161,9 @@ export const PrmDemandeONF: StoryFn = () => ( <FondamentalesEdit etape={etape} completeUpdate={completeUpdate} - demarcheTypeId="oct" - titreTypeId="prm" + machineInfo={MachineInfo.withDate('prm', 'oct', demarcheId, firstEtapeDate)} user={{ role: 'admin', administrationId: 'ope-onf-973-01', ...testBlankUser }} entreprises={entreprises} - firstEtapeDate={firstEtapeDate} /> ) @@ -184,10 +171,8 @@ export const PrmDeplacementDePerimetreONF: StoryFn = () => ( <FondamentalesEdit etape={etape} completeUpdate={completeUpdate} - demarcheTypeId="exp" - titreTypeId="prm" + machineInfo={MachineInfo.withDate('prm', 'exp', demarcheId, firstEtapeDate)} user={{ role: 'admin', administrationId: 'ope-onf-973-01', ...testBlankUser }} entreprises={entreprises} - firstEtapeDate={firstEtapeDate} /> ) diff --git a/packages/ui/src/components/etape/fondamentales-edit.tsx b/packages/ui/src/components/etape/fondamentales-edit.tsx index 2878bb4b8..22a59e70e 100644 --- a/packages/ui/src/components/etape/fondamentales-edit.tsx +++ b/packages/ui/src/components/etape/fondamentales-edit.tsx @@ -2,12 +2,11 @@ import { useState } from '@/utils/vue-tsx-utils' import { DsfrTag } from '../_ui/tag' import { HeritageEdit } from './heritage-edit' import { AutocompleteEntreprises } from './autocomplete-entreprises' -import { CaminoDate, FirstEtapeDate } from 'camino-common/src/date' +import { CaminoDate } from 'camino-common/src/date' import { SubstancesEdit } from './substances-edit' import { canEditAmodiataires, canEditTitulaires, canEditDuree, canEditDates, InputPresence, InputAbsent, InputPresentOptional, dureeIsValide } from 'camino-common/src/permissions/titres-etapes' import { DomaineId } from 'camino-common/src/static/domaines' -import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' -import { getDomaineId, TitreTypeId } from 'camino-common/src/static/titresTypes' +import { getDomaineId } from 'camino-common/src/static/titresTypes' import { computed, ref, defineComponent } from 'vue' import { Entreprise, EntrepriseId } from 'camino-common/src/entreprise' import { User } from 'camino-common/src/roles' @@ -16,16 +15,15 @@ import { DsfrInput } from '../_ui/dsfr-input' import { FlattenEtape } from 'camino-common/src/etape-form' import { ZERO_KM2 } from 'camino-common/src/number' import { fr } from '@codegouvfr/react-dsfr' +import { MachineInfo } from 'camino-common/src/machines' export type EtapeFondamentaleEdit = Pick<FlattenEtape, 'typeId' | 'dateDebut' | 'dateFin' | 'duree' | 'titulaires' | 'amodiataires' | 'substances' | 'perimetre' | 'date' | 'titreDemarcheId'> interface Props { etape: EtapeFondamentaleEdit - demarcheTypeId: DemarcheTypeId - titreTypeId: TitreTypeId user: User entreprises: Entreprise[] completeUpdate: (etape: Props['etape']) => void - firstEtapeDate: FirstEtapeDate + machineInfo: MachineInfo } const dureeToAns = (duree: number | null | undefined) => { @@ -67,24 +65,14 @@ export const FondamentalesEdit = defineComponent<Props>(props => { updateEtape({ amodiataires }) } - const dureeEdit = computed<InputPresence>(() => canEditDuree(props.titreTypeId, props.demarcheTypeId, props.user)) + const dureeEdit = computed<InputPresence>(() => canEditDuree(props.machineInfo, props.user)) const dureeOptionalCheck = computed<boolean>(() => dureeEdit.value.visibility === 'present' && !dureeEdit.value.required) - const dureeValid = computed(() => - dureeIsValide( - props.titreTypeId, - props.demarcheTypeId, - props.etape.typeId, - { value: mois.value + ans.value * 12 }, - props.etape.perimetre.value?.surface ?? ZERO_KM2, - props.etape.titreDemarcheId, - props.firstEtapeDate - ) - ) + const dureeValid = computed(() => dureeIsValide(props.machineInfo, props.etape.typeId, { value: mois.value + ans.value * 12 }, props.etape.perimetre.value?.surface ?? ZERO_KM2)) - const datesEdit = computed<InputAbsent | InputPresentOptional>(() => canEditDates(props.titreTypeId, props.demarcheTypeId, props.etape.typeId, props.user)) + const datesEdit = computed<InputAbsent | InputPresentOptional>(() => canEditDates(props.machineInfo, props.etape.typeId, props.user)) const datesRequiredCheck = computed<boolean>(() => datesEdit.value.visibility === 'present' && datesEdit.value.required) - const titulairesEdit = computed<InputPresence>(() => canEditTitulaires(props.titreTypeId, props.demarcheTypeId, props.user)) + const titulairesEdit = computed<InputPresence>(() => canEditTitulaires(props.machineInfo, props.user)) const titulairesLabel = computed<string>(() => { if (titulairesEdit.value.visibility === 'present') { return 'Titulaires' @@ -94,7 +82,7 @@ export const FondamentalesEdit = defineComponent<Props>(props => { const titulairesRequiredCheck = computed<boolean>(() => titulairesEdit.value.visibility === 'present' && titulairesEdit.value.required) const amodiatairesRequiredCheck = computed<boolean>(() => amodiatairesEdit.value.visibility === 'present' && amodiatairesEdit.value.required) - const amodiatairesEdit = computed<InputPresence>(() => canEditAmodiataires(props.titreTypeId, props.demarcheTypeId, props.user)) + const amodiatairesEdit = computed<InputPresence>(() => canEditAmodiataires(props.machineInfo, props.user)) const amodiatairesLabel = computed<string>(() => { if (amodiatairesEdit.value.visibility === 'present') { return 'Amodiataires' @@ -102,7 +90,7 @@ export const FondamentalesEdit = defineComponent<Props>(props => { return '' }) - const domaineId = computed<DomaineId>(() => getDomaineId(props.titreTypeId)) + const domaineId = computed<DomaineId>(() => getDomaineId(props.machineInfo.titreTypeId)) const titulairesUpdate = (titulaireIds: EntrepriseId[]) => { updateEtape({ titulaires: { ...editedEtape.value.titulaires, value: titulaireIds } }) @@ -329,4 +317,4 @@ export const FondamentalesEdit = defineComponent<Props>(props => { }) // @ts-ignore waiting for https://github.com/vuejs/core/issues/7833 -FondamentalesEdit.props = ['etape', 'demarcheTypeId', 'titreTypeId', 'user', 'entreprises', 'completeUpdate', 'firstEtapeDate'] +FondamentalesEdit.props = ['etape', 'machineInfo', 'user', 'entreprises', 'completeUpdate'] diff --git a/packages/ui/src/components/etape/perimetre-edit.stories.tsx b/packages/ui/src/components/etape/perimetre-edit.stories.tsx index 225e37786..493a0e73c 100644 --- a/packages/ui/src/components/etape/perimetre-edit.stories.tsx +++ b/packages/ui/src/components/etape/perimetre-edit.stories.tsx @@ -10,6 +10,7 @@ import { titreSlugValidator } from 'camino-common/src/validators/titres' import { km2Validator } from 'camino-common/src/number' import { GEO_SYSTEME_IDS } from 'camino-common/src/static/geoSystemes' import { demarcheIdValidator } from 'camino-common/src/demarche' +import { MachineInfo } from 'camino-common/src/machines' const meta: Meta = { title: 'Components/Etape/PerimetreEdit', @@ -100,21 +101,19 @@ const etapeNoHeritage: Props['etape'] = { } const firstEtapeDate = firstEtapeDateValidator.parse('2022-01-01') - +const demarcheId = demarcheIdValidator.parse('demarcheId') const titreSlug = titreSlugValidator.parse('titre-slug') export const EmptyNoHeritage: StoryFn = () => ( <PerimetreEdit initTab="points" apiClient={apiClient} etape={etapeNoHeritage} - titreTypeId="arm" - demarcheTypeId="oct" + machineInfo={MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate)} titreSlug={titreSlug} onEtapeChange={onEtapeChange} onPointsChange={onPointsChange} onForagesChange={onForagesChange} onHeritageChange={onHeritageChange} - firstEtapeDate={firstEtapeDate} /> ) const etapeEmptyHeritage: Props['etape'] = { @@ -146,13 +145,11 @@ export const EmptyHeritage: StoryFn = () => ( onEtapeChange={onEtapeChange} apiClient={apiClient} etape={etapeEmptyHeritage} - titreTypeId="arm" - demarcheTypeId="oct" + machineInfo={MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate)} titreSlug={titreSlug} onPointsChange={onPointsChange} onForagesChange={onForagesChange} onHeritageChange={onHeritageChange} - firstEtapeDate={firstEtapeDate} /> ) @@ -194,13 +191,11 @@ export const Heritage: StoryFn = () => ( onEtapeChange={onEtapeChange} apiClient={apiClient} etape={etapeHeritage} - titreTypeId="arm" - demarcheTypeId="oct" + machineInfo={MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate)} titreSlug={titreSlug} onPointsChange={onPointsChange} onForagesChange={onForagesChange} onHeritageChange={onHeritageChange} - firstEtapeDate={firstEtapeDate} /> ) @@ -229,13 +224,11 @@ export const FilledNoHeritage: StoryFn = () => ( onEtapeChange={onEtapeChange} apiClient={apiClient} etape={etape} - titreTypeId="arm" - demarcheTypeId="oct" + machineInfo={MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate)} titreSlug={titreSlug} onPointsChange={onPointsChange} onForagesChange={onForagesChange} onHeritageChange={onHeritageChange} - firstEtapeDate={firstEtapeDate} /> ) @@ -264,13 +257,11 @@ export const LegacyGeoSysteme: StoryFn = () => ( onEtapeChange={onEtapeChange} apiClient={apiClient} etape={etapeLegacy} - titreTypeId="arm" - demarcheTypeId="oct" + machineInfo={MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDate)} titreSlug={titreSlug} onPointsChange={onPointsChange} onForagesChange={onForagesChange} onHeritageChange={onHeritageChange} - firstEtapeDate={firstEtapeDate} /> ) @@ -378,12 +369,10 @@ export const WithForages: StoryFn = () => ( onEtapeChange={onEtapeChange} apiClient={apiClient} etape={etapeWithForages} - titreTypeId="pxg" - demarcheTypeId="oct" + machineInfo={MachineInfo.withDate('pxg', 'oct', demarcheId, firstEtapeDate)} titreSlug={titreSlug} onPointsChange={onPointsChange} onForagesChange={onForagesChange} onHeritageChange={onHeritageChange} - firstEtapeDate={firstEtapeDate} /> ) diff --git a/packages/ui/src/components/etape/perimetre-edit.tsx b/packages/ui/src/components/etape/perimetre-edit.tsx index de1d6559d..640aa557f 100644 --- a/packages/ui/src/components/etape/perimetre-edit.tsx +++ b/packages/ui/src/components/etape/perimetre-edit.tsx @@ -4,7 +4,6 @@ import { FunctionalComponent, HTMLAttributes, defineComponent, ref } from 'vue' import { DsfrButton } from '../_ui/dsfr-button' import { ApiClient } from '@/api/api-client' import { FeatureCollectionForages, FeatureCollectionPoints, GeojsonInformations } from 'camino-common/src/perimetre' -import { TitreTypeId } from 'camino-common/src/static/titresTypes' import { DsfrPerimetre } from '../_common/dsfr-perimetre' import { TitreSlug } from 'camino-common/src/validators/titres' import { CaminoApiAlert } from '../_ui/alert' @@ -15,27 +14,24 @@ import { canHaveForages } from 'camino-common/src/permissions/titres' import { CoreEtapeCreationOrModification } from './etape-api-client' import { CaminoError } from 'camino-common/src/zod-tools' import { perimetreIsValide } from 'camino-common/src/permissions/titres-etapes' -import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' -import { FirstEtapeDate } from 'camino-common/src/date' +import { MachineInfo } from 'camino-common/src/machines' export interface Props { apiClient: Pick<ApiClient, 'uploadTempDocument' | 'geojsonImport' | 'geojsonPointsImport' | 'geojsonForagesImport'> etape: Pick<CoreEtapeCreationOrModification, 'perimetre' | 'date' | 'typeId' | 'titreDemarcheId'> - titreTypeId: TitreTypeId - demarcheTypeId: DemarcheTypeId + machineInfo: MachineInfo titreSlug: TitreSlug onEtapeChange: (geojsonInformations: GeojsonInformations) => void onHeritageChange: (heritage: Props['etape']['perimetre']) => void onPointsChange: (geojson4326Points: FeatureCollectionPoints, geojsonOriginePoints: FeatureCollectionPoints) => void onForagesChange: (geojson4326Forages: FeatureCollectionForages, geojsonOrigineForages: FeatureCollectionForages) => void initTab?: 'points' | 'carte' - firstEtapeDate: FirstEtapeDate } type DisplayPerimetreProps = { perimetre: Props['etape']['perimetre'] | null titreSlug: TitreSlug - titreTypeId: TitreTypeId + machineInfo: MachineInfo initTab?: 'points' | 'carte' class?: HTMLAttributes['class'] } @@ -61,7 +57,7 @@ const DisplayPerimetre: FunctionalComponent<DisplayPerimetreProps> = props => { surface: props.perimetre.value.surface ?? null, }} titreSlug={props.titreSlug} - titreTypeId={props.titreTypeId} + machineInfo={props.machineInfo} id="perimetre_edit" initTab={props.initTab ?? 'carte'} /> @@ -105,7 +101,7 @@ export const PerimetreEdit = defineComponent<Props>(props => { const result = (value: GeojsonInformations | CaminoError<string>) => { if ('geojson4326_perimetre' in value) { - const isValid = perimetreIsValide(props.titreTypeId, props.demarcheTypeId, props.etape.typeId, value.surface, props.etape.titreDemarcheId, props.firstEtapeDate) + const isValid = perimetreIsValide(props.machineInfo, props.etape.typeId, value.surface) if (!isValid.valid) { importError.value = { message: isValid.message } } else { @@ -152,26 +148,28 @@ export const PerimetreEdit = defineComponent<Props>(props => { {isNotNullNorUndefined(props.etape.perimetre.value?.geojson4326Perimetre) && isNotNullNorUndefined(props.etape.perimetre.value?.geojsonOrigineGeoSystemeId) ? ( <> <DsfrButton class="fr-ml-2w" onClick={openPointsPopup} buttonType="secondary" title="Éditer les points" /> - {canHaveForages(props.titreTypeId) ? <DsfrButton class="fr-ml-2w" onClick={openForagesPopup} buttonType="secondary" title="Éditer les forages" /> : null} + {canHaveForages(props.machineInfo) ? <DsfrButton class="fr-ml-2w" onClick={openForagesPopup} buttonType="secondary" title="Éditer les forages" /> : null} </> ) : null} {isNotNullNorUndefined(importError.value) ? <CaminoApiAlert class="fr-mt-2w" caminoApiError={importError.value} /> : null} - <DisplayPerimetre class="fr-mt-2w" perimetre={props.etape.perimetre} titreSlug={props.titreSlug} initTab={props.initTab} titreTypeId={props.titreTypeId} /> + <DisplayPerimetre class="fr-mt-2w" perimetre={props.etape.perimetre} titreSlug={props.titreSlug} initTab={props.initTab} machineInfo={props.machineInfo} /> </div> )} read={heritage => ( <DisplayPerimetre perimetre={isNotNullNorUndefined(heritage) ? { ...props.etape.perimetre, value: heritage.value } : null} titreSlug={props.titreSlug} - titreTypeId={props.titreTypeId} + machineInfo={props.machineInfo} initTab={props.initTab} /> )} /> - {importPerimetrePopup.value ? <PerimetreImportPopup close={closePerimetrePopup} result={result} apiClient={props.apiClient} titreTypeId={props.titreTypeId} titreSlug={props.titreSlug} /> : null} + {importPerimetrePopup.value ? ( + <PerimetreImportPopup close={closePerimetrePopup} result={result} apiClient={props.apiClient} titreTypeId={props.machineInfo.titreTypeId} titreSlug={props.titreSlug} /> + ) : null} {importPointsPopup.value && isNotNullNorUndefined(props.etape.perimetre.value?.geojsonOrigineGeoSystemeId) ? ( <PointsImportPopup close={closePointsPopup} result={resultPoints} geoSystemeId={props.etape.perimetre.value.geojsonOrigineGeoSystemeId} apiClient={props.apiClient} /> @@ -185,4 +183,4 @@ export const PerimetreEdit = defineComponent<Props>(props => { }) // @ts-ignore waiting for https://github.com/vuejs/core/issues/7833 -PerimetreEdit.props = ['etape', 'apiClient', 'titreTypeId', 'demarcheTypeId', 'titreSlug', 'onEtapeChange', 'initTab', 'onPointsChange', 'onForagesChange', 'onHeritageChange', 'firstEtapeDate'] +PerimetreEdit.props = ['etape', 'apiClient', 'machineInfo', 'titreSlug', 'onEtapeChange', 'initTab', 'onPointsChange', 'onForagesChange', 'onHeritageChange'] diff --git a/packages/ui/src/components/etape/sections-edit.stories.tsx b/packages/ui/src/components/etape/sections-edit.stories.tsx index 35ded23dc..f94e3febd 100644 --- a/packages/ui/src/components/etape/sections-edit.stories.tsx +++ b/packages/ui/src/components/etape/sections-edit.stories.tsx @@ -1,7 +1,9 @@ import { SectionsEdit } from './sections-edit' import { Meta, StoryFn } from '@storybook/vue3' import { action } from '@storybook/addon-actions' -import { toCaminoDate } from 'camino-common/src/date' +import { firstEtapeDateValidator, toCaminoDate } from 'camino-common/src/date' +import { MachineInfo } from 'camino-common/src/machines' +import { demarcheIdValidator } from 'camino-common/src/demarche' const meta: Meta = { title: 'Components/Etape/SectionsEdit', @@ -12,11 +14,11 @@ export default meta const completeUpdate = action('completeUpdate') +const demarcheId = demarcheIdValidator.parse('demarcheId') export const SansHeritage: StoryFn = () => ( <SectionsEdit completeUpdate={completeUpdate} - demarcheTypeId="oct" - titreTypeId="arm" + machineInfo={MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDateValidator.parse('2024-01-01'))} etape={{ typeId: 'mfr', contenu: { arm: { mecanise: { value: true, heritee: false, etapeHeritee: null }, franchissements: { value: null, heritee: false, etapeHeritee: null } } }, @@ -28,8 +30,7 @@ export const SansHeritage: StoryFn = () => ( export const AvecHeritageActif: StoryFn = () => ( <SectionsEdit completeUpdate={completeUpdate} - demarcheTypeId="oct" - titreTypeId="arm" + machineInfo={MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDateValidator.parse('2024-01-01'))} etape={{ date: toCaminoDate('2024-01-01'), typeId: 'mod', @@ -46,8 +47,7 @@ export const AvecHeritageActif: StoryFn = () => ( export const AvecHeritage: StoryFn = () => ( <SectionsEdit completeUpdate={completeUpdate} - demarcheTypeId="oct" - titreTypeId="arm" + machineInfo={MachineInfo.withDate('arm', 'oct', demarcheId, firstEtapeDateValidator.parse('2024-01-01'))} etape={{ date: toCaminoDate('2024-01-01'), typeId: 'mod', @@ -64,8 +64,7 @@ export const AvecHeritage: StoryFn = () => ( export const DecisionJorf: StoryFn = () => ( <SectionsEdit completeUpdate={completeUpdate} - demarcheTypeId="pro" - titreTypeId="pcc" + machineInfo={MachineInfo.withDate('pcc', 'pro', demarcheId, firstEtapeDateValidator.parse('2000-05-16'))} etape={{ date: toCaminoDate('2000-05-16'), typeId: 'dpu', diff --git a/packages/ui/src/components/etape/sections-edit.tsx b/packages/ui/src/components/etape/sections-edit.tsx index f610aa6b9..9172806f2 100644 --- a/packages/ui/src/components/etape/sections-edit.tsx +++ b/packages/ui/src/components/etape/sections-edit.tsx @@ -1,17 +1,15 @@ import { computed, defineComponent } from 'vue' -import { TitreTypeId } from 'camino-common/src/static/titresTypes' -import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' import { getSections, getSectionsWithValue } from 'camino-common/src/static/titresTypes_demarchesTypes_etapesTypes/sections' import { isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty } from 'camino-common/src/typescript-tools' import { useState } from '../../utils/vue-tsx-utils' import { SectionWithValue } from 'camino-common/src/sections' import { SectionElementWithValueEdit } from './section-element-with-value-edit' import { FlattenedContenuElement, FlattenEtape } from 'camino-common/src/etape-form' +import { MachineInfo } from 'camino-common/src/machines' export type SectionsEditEtape = Pick<FlattenEtape, 'typeId' | 'contenu' | 'date'> type Props = { - titreTypeId: TitreTypeId - demarcheTypeId: DemarcheTypeId + machineInfo: MachineInfo etape: SectionsEditEtape completeUpdate: (etape: Props['etape']) => void } @@ -29,7 +27,7 @@ export const SectionsEdit = defineComponent<Props>(props => { } const sections = computed(() => { - return getSections(props.titreTypeId, props.demarcheTypeId, props.etape.typeId) + return getSections(props.machineInfo, props.etape.typeId) }) const sectionsWithValue = computed<SectionWithValue[]>(() => { if (isNotNullNorUndefined(editedEtape.value.contenu)) { @@ -63,4 +61,4 @@ export const SectionsEdit = defineComponent<Props>(props => { }) // @ts-ignore waiting for https://github.com/vuejs/core/issues/7833 -SectionsEdit.props = ['etape', 'titreTypeId', 'demarcheTypeId', 'completeUpdate'] +SectionsEdit.props = ['etape', 'machineInfo', 'completeUpdate'] diff --git a/packages/ui/src/components/titre.stories.tsx b/packages/ui/src/components/titre.stories.tsx index e611c50c3..d829c06a4 100644 --- a/packages/ui/src/components/titre.stories.tsx +++ b/packages/ui/src/components/titre.stories.tsx @@ -132,6 +132,7 @@ const titre = { id: demarcheIdValidator.parse('id-demarche-1'), demarche_type_id: 'oct', slug: demarcheSlug, + machine_id: 'ProcedureSpecifique', demarche_date_debut: toCaminoDate('4000-01-01'), demarche_date_fin: toCaminoDate('4000-01-01'), demarche_statut_id: 'acc', @@ -380,7 +381,7 @@ const chantePieApiClient: PropsApiClient = { getTitreAction(titreIdOrSlug) // prettier-ignore - const chantepieData = titreGetValidator.parse({"id":"Ju80kBYMoDstD5J6H8wqWRdo","titre_visibilite":"Publique","nom":"Chantepie","slug":"m-cx-chantepie-1988","titre_type_id":"cxm","titre_statut_id":"val","titre_doublon":null,"references":[{"nom":"2013-0224-MI","referenceTypeId":"deb"}],"titre_last_modified_date":"2023-10-12","demarches":[{"id":"PpD4be1fwbWJ7TZCdwvZj0vQ","demarche_visibilite":"Publique","slug":"m-cx-chantepie-1988-oct01","description":null,"etapes":[{"etape_type_id":"dpu","fondamentale":{"date_debut":null,"date_fin":null,"duree":600,"substances":["auru","arge","cuiv","ferx","plom","souf","zinc","scoc"],"titulaireIds":["fr-632022711"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-0.105658320330431,48.1489209342693],[-0.115003633563279,48.1398379979624],[-0.0996023094257926,48.1209828190687],[-0.0852402595925762,48.1212930049111],[-0.0616864580218711,48.1486971325525],[-0.105658320330431,48.1489209342693]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.105658320330431,48.1489209342693]},"properties":{"nom":"A","description":"Intersection de l'axe de la route départementale n° 103, joignant Rouez et Crissé et de la droite joignant l'intersection de l'axe de la rivière La Vègre avec la limite des communes de Sillé-le-Guillaume et de Rouez, d'une part, au sommet B défini ci-après"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.0616864580218711,48.1486971325525]},"properties":{"nom":"B","description":"Intersection de l'axe de la route départementale n° 304 allant de Sillé-le-Guillaume à Conlie et de l'axe de la route départementale n° 167 allant à Rouez"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.0852402595925762,48.1212930049111]},"properties":{"nom":"C","description":"Intersection de la droite joignant l'axe du clocher de Sillé-le-Guillaume et l'axe du clocher de Tennie, et de la droite joignant l'axe du clocher de Parennes et l'axe du clocher de Conlie"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.0996023094257926,48.1209828190687]},"properties":{"nom":"D","description":"Intersection de la droite joignant l'axe du clocher de Parennes et l'axe du clocher de Conlie et de la droite joignant l'axe du clocher de Rouez et l'axe du clocher de Bernay"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.115003633563279,48.1398379979624]},"properties":{"nom":"E","description":"Axe du clocher de Rouez"}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[418280,1052710],[421550,1052580],[419700,1049590],[418630,1049590],[417552,1051723],[418280,1052710]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[418280,1052710]},"properties":{"nom":"A","description":"Intersection de l’axe de la route départementale n° 103, joignant Rouez et Crissé et de la droite joignant l’intersection de l’axe de la rivière La Vègre avec la limite des communes de Sillé-le-Guillaume et de Rouez, d’une part, au sommet B défini ci-après"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[421550,1052580]},"properties":{"nom":"B","description":"Intersection de l’axe de la route départementale n° 304 allant de Sillé-le-Guillaume à Conlie et de l’axe de la route départementale n° 167 allant à Rouez"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[419700,1049590]},"properties":{"nom":"C","description":"Intersection de la droite joignant l’axe du clocher de Sillé-le-Guillaume et l’axe du clocher de Tennie, et de la droite joignant l’axe du clocher de Parennes et l’axe du clocher de Conlie"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[418630,1049590]},"properties":{"nom":"D","description":"Intersection de la droite joignant l’axe du clocher de Parennes et l’axe du clocher de Conlie et de la droite joignant l’axe du clocher de Rouez et l’axe du clocher de Bernay"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[417552,1051723]},"properties":{"nom":"E","description":"Axe du clocher de Rouez"}}]},"geojson_origine_geo_systeme_id":"27571","geojson4326_forages":null,"geojson_origine_forages":null,"surface":8,"communes":[{"id":"72256","nom":"Rouez"},{"id":"72351","nom":"Tennie"}],"secteurs_maritimes":[],"sdom_zones":[],"forets":[]}},"etape_statut_id":"fai","is_brouillon":false,"date":"1988-09-01","id":"OxqtxQwW0B3AUIHFR7k32Ycl","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-chantepie-1988-oct01-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":false,"type":"text","value":"JORFTEXT000000681488"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"INDE8800659D"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"dex","fondamentale":{"date_debut":null,"date_fin":null,"duree":600,"substances":["auru","arge","cuiv","ferx","plom","souf","zinc","scoc"],"titulaireIds":["fr-632022711"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-0.105658320330431,48.1489209342693],[-0.115003633563279,48.1398379979624],[-0.0996023094257926,48.1209828190687],[-0.0852402595925762,48.1212930049111],[-0.0616864580218711,48.1486971325525],[-0.105658320330431,48.1489209342693]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.105658320330431,48.1489209342693]},"properties":{"nom":"A","description":"Intersection de l'axe de la route départementale n° 103, joignant Rouez et Crissé et de la droite joignant l'intersection de l'axe de la rivière La Vègre avec la limite des communes de Sillé-le-Guillaume et de Rouez, d'une part, au sommet B défini ci-après"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.0616864580218711,48.1486971325525]},"properties":{"nom":"B","description":"Intersection de l'axe de la route départementale n° 304 allant de Sillé-le-Guillaume à Conlie et de l'axe de la route départementale n° 167 allant à Rouez"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.0852402595925762,48.1212930049111]},"properties":{"nom":"C","description":"Intersection de la droite joignant l'axe du clocher de Sillé-le-Guillaume et l'axe du clocher de Tennie, et de la droite joignant l'axe du clocher de Parennes et l'axe du clocher de Conlie"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.0996023094257926,48.1209828190687]},"properties":{"nom":"D","description":"Intersection de la droite joignant l'axe du clocher de Parennes et l'axe du clocher de Conlie et de la droite joignant l'axe du clocher de Rouez et l'axe du clocher de Bernay"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.115003633563279,48.1398379979624]},"properties":{"nom":"E","description":"Axe du clocher de Rouez"}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[418280,1052710],[421550,1052580],[419700,1049590],[418630,1049590],[417552,1051723],[418280,1052710]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[418280,1052710]},"properties":{"nom":"A","description":"Intersection de l’axe de la route départementale n° 103, joignant Rouez et Crissé et de la droite joignant l’intersection de l’axe de la rivière La Vègre avec la limite des communes de Sillé-le-Guillaume et de Rouez, d’une part, au sommet B défini ci-après"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[421550,1052580]},"properties":{"nom":"B","description":"Intersection de l’axe de la route départementale n° 304 allant de Sillé-le-Guillaume à Conlie et de l’axe de la route départementale n° 167 allant à Rouez"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[419700,1049590]},"properties":{"nom":"C","description":"Intersection de la droite joignant l’axe du clocher de Sillé-le-Guillaume et l’axe du clocher de Tennie, et de la droite joignant l’axe du clocher de Parennes et l’axe du clocher de Conlie"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[418630,1049590]},"properties":{"nom":"D","description":"Intersection de la droite joignant l’axe du clocher de Parennes et l’axe du clocher de Conlie et de la droite joignant l’axe du clocher de Rouez et l’axe du clocher de Bernay"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[417552,1051723]},"properties":{"nom":"E","description":"Axe du clocher de Rouez"}}]},"geojson_origine_geo_systeme_id":"27571","geojson4326_forages":null,"geojson_origine_forages":null,"surface":8,"communes":[{"id":"72256","nom":"Rouez"},{"id":"72351","nom":"Tennie"}],"secteurs_maritimes":[],"sdom_zones":[],"forets":[]}},"etape_statut_id":"acc","is_brouillon":false,"date":"1988-08-24","id":"XkNmBmjc6YYY6OEncdCAldnU","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-chantepie-1988-oct01-dex01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":true,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]}],"demarche_type_id":"oct","demarche_statut_id":"acc","demarche_date_debut":"1988-09-01","demarche_date_fin":"2038-09-01","ordre":1},{"id":"mkPvJYXFO2InPppXamCRo2Cv","demarche_visibilite":"Publique","slug":"m-cx-chantepie-1988-mut01","description":null,"etapes":[{"etape_type_id":"dpu","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":["fr-409160132"],"amodiataireIds":null,"perimetre":null},"etape_statut_id":"fai","is_brouillon":false,"date":"2000-06-06","id":"lc3diJKRphb029ufvF73FlSn","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-chantepie-1988-mut01-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":false,"type":"text","value":"JORFTEXT000000765254"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"ECOI0000251A"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"dex","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":["fr-409160132"],"amodiataireIds":null,"perimetre":null},"etape_statut_id":"acc","is_brouillon":false,"date":"2000-05-25","id":"2n1RaQcCxZMVta2Qfv1pUIRS","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-chantepie-1988-mut01-dex01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":true,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]}],"demarche_type_id":"mut","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"ordre":2}],"nb_activites_to_do":null}) + const chantepieData = titreGetValidator.parse({"id":"Ju80kBYMoDstD5J6H8wqWRdo","nom":"Chantepie","slug":"m-cx-chantepie-1988","titre_type_id":"cxm","titre_statut_id":"val","titre_visibilite":"Publique","titre_doublon":null,"references":[{"nom":"2013-0224-MI","referenceTypeId":"deb"}],"titre_last_modified_date":null,"demarches":[{"id":"PpD4be1fwbWJ7TZCdwvZj0vQ","slug":"m-cx-chantepie-1988-oct01","description":null,"etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"1988-09-01","id":"OxqtxQwW0B3AUIHFR7k32Ycl","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-chantepie-1988-oct01-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":"JORFTEXT000000681488"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"INDE8800659D"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":600,"substances":["auru","arge","cuiv","ferx","plom","souf","zinc","scoc"],"titulaireIds":["fr-632022711"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-0.105658320330431,48.1489209342693],[-0.115003633563279,48.1398379979624],[-0.0996023094257926,48.1209828190687],[-0.0852402595925762,48.1212930049111],[-0.0616864580218711,48.1486971325525],[-0.105658320330431,48.1489209342693]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.105658320330431,48.1489209342693]},"properties":{"nom":"A","description":"Intersection de l'axe de la route départementale n° 103, joignant Rouez et Crissé et de la droite joignant l'intersection de l'axe de la rivière La Vègre avec la limite des communes de Sillé-le-Guillaume et de Rouez, d'une part, au sommet B défini ci-après"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.0616864580218711,48.1486971325525]},"properties":{"nom":"B","description":"Intersection de l'axe de la route départementale n° 304 allant de Sillé-le-Guillaume à Conlie et de l'axe de la route départementale n° 167 allant à Rouez"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.0852402595925762,48.1212930049111]},"properties":{"nom":"C","description":"Intersection de la droite joignant l'axe du clocher de Sillé-le-Guillaume et l'axe du clocher de Tennie, et de la droite joignant l'axe du clocher de Parennes et l'axe du clocher de Conlie"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.0996023094257926,48.1209828190687]},"properties":{"nom":"D","description":"Intersection de la droite joignant l'axe du clocher de Parennes et l'axe du clocher de Conlie et de la droite joignant l'axe du clocher de Rouez et l'axe du clocher de Bernay"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.115003633563279,48.1398379979624]},"properties":{"nom":"E","description":"Axe du clocher de Rouez"}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[418280,1052710],[421550,1052580],[419700,1049590],[418630,1049590],[417552,1051723],[418280,1052710]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[418280,1052710]},"properties":{"nom":"A","description":"Intersection de l’axe de la route départementale n° 103, joignant Rouez et Crissé et de la droite joignant l’intersection de l’axe de la rivière La Vègre avec la limite des communes de Sillé-le-Guillaume et de Rouez, d’une part, au sommet B défini ci-après"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[421550,1052580]},"properties":{"nom":"B","description":"Intersection de l’axe de la route départementale n° 304 allant de Sillé-le-Guillaume à Conlie et de l’axe de la route départementale n° 167 allant à Rouez"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[419700,1049590]},"properties":{"nom":"C","description":"Intersection de la droite joignant l’axe du clocher de Sillé-le-Guillaume et l’axe du clocher de Tennie, et de la droite joignant l’axe du clocher de Parennes et l’axe du clocher de Conlie"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[418630,1049590]},"properties":{"nom":"D","description":"Intersection de la droite joignant l’axe du clocher de Parennes et l’axe du clocher de Conlie et de la droite joignant l’axe du clocher de Rouez et l’axe du clocher de Bernay"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[417552,1051723]},"properties":{"nom":"E","description":"Axe du clocher de Rouez"}}]},"geojson_origine_geo_systeme_id":"27571","geojson4326_forages":null,"geojson_origine_forages":null,"surface":8,"communes":[{"id":"72256","nom":"Rouez"},{"id":"72351","nom":"Tennie"}],"secteurs_maritimes":[],"sdom_zones":[],"forets":[]}},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"1988-08-24","id":"XkNmBmjc6YYY6OEncdCAldnU","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-chantepie-1988-oct01-dex01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":600,"substances":["auru","arge","cuiv","ferx","plom","souf","zinc","scoc"],"titulaireIds":["fr-632022711"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-0.105658320330431,48.1489209342693],[-0.115003633563279,48.1398379979624],[-0.0996023094257926,48.1209828190687],[-0.0852402595925762,48.1212930049111],[-0.0616864580218711,48.1486971325525],[-0.105658320330431,48.1489209342693]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.105658320330431,48.1489209342693]},"properties":{"nom":"A","description":"Intersection de l'axe de la route départementale n° 103, joignant Rouez et Crissé et de la droite joignant l'intersection de l'axe de la rivière La Vègre avec la limite des communes de Sillé-le-Guillaume et de Rouez, d'une part, au sommet B défini ci-après"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.0616864580218711,48.1486971325525]},"properties":{"nom":"B","description":"Intersection de l'axe de la route départementale n° 304 allant de Sillé-le-Guillaume à Conlie et de l'axe de la route départementale n° 167 allant à Rouez"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.0852402595925762,48.1212930049111]},"properties":{"nom":"C","description":"Intersection de la droite joignant l'axe du clocher de Sillé-le-Guillaume et l'axe du clocher de Tennie, et de la droite joignant l'axe du clocher de Parennes et l'axe du clocher de Conlie"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.0996023094257926,48.1209828190687]},"properties":{"nom":"D","description":"Intersection de la droite joignant l'axe du clocher de Parennes et l'axe du clocher de Conlie et de la droite joignant l'axe du clocher de Rouez et l'axe du clocher de Bernay"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-0.115003633563279,48.1398379979624]},"properties":{"nom":"E","description":"Axe du clocher de Rouez"}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[418280,1052710],[421550,1052580],[419700,1049590],[418630,1049590],[417552,1051723],[418280,1052710]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[418280,1052710]},"properties":{"nom":"A","description":"Intersection de l’axe de la route départementale n° 103, joignant Rouez et Crissé et de la droite joignant l’intersection de l’axe de la rivière La Vègre avec la limite des communes de Sillé-le-Guillaume et de Rouez, d’une part, au sommet B défini ci-après"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[421550,1052580]},"properties":{"nom":"B","description":"Intersection de l’axe de la route départementale n° 304 allant de Sillé-le-Guillaume à Conlie et de l’axe de la route départementale n° 167 allant à Rouez"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[419700,1049590]},"properties":{"nom":"C","description":"Intersection de la droite joignant l’axe du clocher de Sillé-le-Guillaume et l’axe du clocher de Tennie, et de la droite joignant l’axe du clocher de Parennes et l’axe du clocher de Conlie"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[418630,1049590]},"properties":{"nom":"D","description":"Intersection de la droite joignant l’axe du clocher de Parennes et l’axe du clocher de Conlie et de la droite joignant l’axe du clocher de Rouez et l’axe du clocher de Bernay"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[417552,1051723]},"properties":{"nom":"E","description":"Axe du clocher de Rouez"}}]},"geojson_origine_geo_systeme_id":"27571","geojson4326_forages":null,"geojson_origine_forages":null,"surface":8,"communes":[{"id":"72256","nom":"Rouez"},{"id":"72351","nom":"Tennie"}],"secteurs_maritimes":[],"sdom_zones":[],"forets":[]}},"etape_type_id":"dex"}],"demarche_type_id":"oct","demarche_statut_id":"acc","demarche_date_debut":"1988-09-01","demarche_date_fin":"2038-09-01","demarche_visibilite":"Publique","machine_id":null,"ordre":1},{"id":"mkPvJYXFO2InPppXamCRo2Cv","slug":"m-cx-chantepie-1988-mut01","description":null,"etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"2000-06-06","id":"lc3diJKRphb029ufvF73FlSn","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-chantepie-1988-mut01-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":"JORFTEXT000000765254"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"ECOI0000251A"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":["fr-409160132"],"amodiataireIds":null,"perimetre":null},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"2000-05-25","id":"2n1RaQcCxZMVta2Qfv1pUIRS","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-chantepie-1988-mut01-dex01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":["fr-409160132"],"amodiataireIds":null,"perimetre":null},"etape_type_id":"dex"}],"demarche_type_id":"mut","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"demarche_visibilite":"Publique","machine_id":null,"ordre":2}],"nb_activites_to_do":null}) chantepieData.nom = 'Chantepie avec un titre assez long' chantepieData.nb_activites_to_do = 2 @@ -433,7 +434,7 @@ const criqueAdolpheApiClient: PropsApiClient = { getTitreAction(titreIdOrSlug) // prettier-ignore - const criqueAdolpheData = titreGetValidator.parse({"id":"tbFvGIDboAzxTb54GQyghTyc","titre_visibilite":"Publique","nom":"Crique Adolphe","slug":"m-ar-crique-adolphe-2023","titre_type_id":"arm","titre_statut_id":"ech","titre_doublon":null,"references":[{"nom":"2022-032","referenceTypeId":"ptm"},{"nom":"AR 2022-027","referenceTypeId":"onf"}],"titre_last_modified_date":"2023-10-20","demarches":[{"id":"yAvBOMdHDsyES7phbS5hRKLA","demarche_visibilite":"Publique","slug":"m-ar-crique-adolphe-2023-oct01","description":null,"etapes":[{"etape_type_id":"sco","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":null,"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"fai","is_brouillon":false,"date":"2023-09-19","id":"5649942721fd9f3478381ae9","ordre":15,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-crique-adolphe-2023-oct01-sco01","sections_with_values":[{"id":"suivi","nom":"Suivi de la démarche","elements":[{"id":"signataire","nom":"Signataire ONF","description":"Prénom et nom du représentant légal du titulaire de l'ONF","optionnel":true,"type":"text","value":null},{"id":"titulaire","nom":"Signataire titulaire","description":"Prénom et nom du représentant légal du titulaire de l'autorisation","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"sca","etape_statut_id":"fai","is_brouillon":false,"date":"2023-01-11","id":"WLXKWB9Fv17gm2gTJYIXnTyX","ordre":10,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-crique-adolphe-2023-oct01-sca01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"aca","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":null,"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"fav","is_brouillon":false,"date":"2023-01-11","id":"oXXG5ToIYbw8MvdYPX7sMMAP","ordre":11,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-crique-adolphe-2023-oct01-aca01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"rde","etape_statut_id":"fav","is_brouillon":false,"date":"2022-12-29","id":"y0SCXGJ1OBYSthcWyojyOLZX","ordre":8,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-crique-adolphe-2023-oct01-rde01","sections_with_values":[{"id":"deal","nom":"DEAL","elements":[{"id":"numero-dossier-deal-eau","nom":"Numéro de dossier","description":"Numéro de dossier DEAL Service eau","optionnel":true,"type":"text","value":""},{"id":"numero-recepisse","nom":"Numéro de récépissé","description":"Numéro de récépissé émis par la DEAL Service eau","optionnel":true,"type":"text","value":"R03-2022-12-29-00005"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"mcr","etape_statut_id":"fav","is_brouillon":false,"date":"2022-12-05","id":"0vdB4jaJbpIpyUnIZkKPsmCm","ordre":7,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-crique-adolphe-2023-oct01-mcr01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"mfr", "demarche_id_en_concurrence": null, "demarches_consentement": [],"fondamentale":{"date_debut":null,"date_fin":null,"duree":4,"substances":["auru"],"titulaireIds":["fr-794312231"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.58181013905019,3.8309654861273],[-53.58178306390299,3.8219278216269807],[-53.572785590706495,3.82195493825841],[-53.57281257175149,3.8309926670647294],[-53.58181013905019,3.8309654861273]]],[[[-53.60031408473134,3.8224780986447566],[-53.59891645305842,3.8181831495446303],[-53.58181205656814,3.82379854768971],[-53.58320964990986,3.828093576227541],[-53.60031408473134,3.8224780986447566]]],[[[-53.583861926103765,3.8502114455117433],[-53.592379712320195,3.834289122043602],[-53.588417035915334,3.8321501920354253],[-53.57989914401643,3.8480725119510217],[-53.583861926103765,3.8502114455117433]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.58181013905019,3.8309654861273]},"properties":{"nom":"S1","description":"ARM1.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.57281257175149,3.8309926670647294]},"properties":{"nom":"S2","description":"ARM1.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.572785590706495,3.82195493825841]},"properties":{"nom":"S3","description":"ARM1.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.58178306390299,3.8219278216269807]},"properties":{"nom":"S4","description":"ARM1.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.60031408473134,3.8224780986447566]},"properties":{"nom":"S5","description":"ARM2.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.58320964990986,3.828093576227541]},"properties":{"nom":"S6","description":"ARM2.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.58181205656814,3.82379854768971]},"properties":{"nom":"S7","description":"ARM2.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.59891645305842,3.8181831495446303]},"properties":{"nom":"S8","description":"ARM2.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.583861926103765,3.8502114455117433]},"properties":{"nom":"S9","description":"ARM3.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.57989914401643,3.8480725119510217]},"properties":{"nom":"S10","description":"ARM3.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.588417035915334,3.8321501920354253]},"properties":{"nom":"S11","description":"ARM3.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.592379712320195,3.834289122043602]},"properties":{"nom":"S12","description":"ARM3.3"}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[213250,423875],[214250,423875],[214250,422875],[213250,422875],[213250,423875]]],[[[211190.6,422942.1],[213093.5,423557.7],[213247.4,423082],[211344.5,422466.4],[211190.6,422942.1]]],[[[213028.4,426005.2],[213468.1,425767.2],[212516.1,424008.3],[212076.4,424246.3],[213028.4,426005.2]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[213250,423875]},"properties":{"nom":"S1","description":"ARM1.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[214250,423875]},"properties":{"nom":"S2","description":"ARM1.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[214250,422875]},"properties":{"nom":"S3","description":"ARM1.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[213250,422875]},"properties":{"nom":"S4","description":"ARM1.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[211190.6,422942.1]},"properties":{"nom":"S5","description":"ARM2.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[213093.5,423557.7]},"properties":{"nom":"S6","description":"ARM2.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[213247.4,423082]},"properties":{"nom":"S7","description":"ARM2.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[211344.5,422466.4]},"properties":{"nom":"S8","description":"ARM2.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[213028.4,426005.2]},"properties":{"nom":"S9","description":"ARM3.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[213468.1,425767.2]},"properties":{"nom":"S10","description":"ARM3.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[212516.1,424008.3]},"properties":{"nom":"S11","description":"ARM3.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[212076.4,424246.3]},"properties":{"nom":"S12","description":"ARM3.3"}}]},"geojson_origine_geo_systeme_id":"2972","geojson4326_forages":null,"geojson_origine_forages":null,"surface":3,"communes":[{"id":"97353","nom":"Maripasoula"}],"secteurs_maritimes":[],"sdom_zones":[],"forets":[]}},"etape_statut_id":"fai","is_brouillon":false,"date":"2022-11-08","id":"pwqOEAsAmaWi0o24QiVeVZ40","ordre":3,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-crique-adolphe-2023-oct01-mfr01","sections_with_values":[{"id":"arm","nom":"Caractéristiques ARM","elements":[{"id":"mecanise","nom":"Prospection mécanisée","description":"","optionnel":false,"type":"radio","value":true},{"id":"franchissements","nom":"Franchissements de cours d'eau","description":"Nombre de franchissements de cours d'eau","optionnel":true,"type":"integer","value":12}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"men","etape_statut_id":"fai","is_brouillon":false,"date":"2022-11-08","id":"pF4UG6UrCOJmKjtgmtpwthTQ","ordre":4,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-crique-adolphe-2023-oct01-men01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"dae","etape_statut_id":"exe","is_brouillon":false,"date":"2022-09-26","id":"KA7tyvIdlqQmmVOuVjEl0Hdt","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-crique-adolphe-2023-oct01-dae01","sections_with_values":[{"id":"mea","nom":"Mission autorité environnementale","elements":[{"id":"arrete","nom":"Arrêté préfectoral","description":"Numéro de l'arrêté préfectoral portant décision dans le cadre de l’examen au cas par cas du projet d’autorisation de recherche minière","optionnel":true,"type":"text","value":"R03-2022-09-26-00002"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]}],"demarche_type_id":"oct","demarche_statut_id":"acc","demarche_date_debut":"2023-09-19","demarche_date_fin":"2024-01-19","ordre":1}],"nb_activites_to_do":null}) + const criqueAdolpheData = titreGetValidator.parse({"id":"tbFvGIDboAzxTb54GQyghTyc","nom":"Crique Adolphe","slug":"m-ar-crique-adolphe-2023","titre_type_id":"arm","titre_statut_id":"ech","titre_visibilite":"Publique","titre_doublon":null,"references":[{"nom":"2022-032","referenceTypeId":"ptm"},{"nom":"AR 2022-027","referenceTypeId":"onf"}],"titre_last_modified_date":null,"demarches":[{"id":"yAvBOMdHDsyES7phbS5hRKLA","slug":"m-ar-crique-adolphe-2023-oct01","description":null,"etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"2023-09-19","id":"5649942721fd9f3478381ae9","ordre":15,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-crique-adolphe-2023-oct01-sco01","sections_with_values":[{"id":"suivi","nom":"Suivi de la démarche","elements":[{"id":"signataire","nom":"Signataire ONF","description":"Prénom et nom du représentant légal du titulaire de l'ONF","optionnel":true,"type":"text","value":null},{"id":"titulaire","nom":"Signataire titulaire","description":"Prénom et nom du représentant légal du titulaire de l'autorisation","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":null,"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"sco"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2023-01-11","id":"WLXKWB9Fv17gm2gTJYIXnTyX","ordre":10,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-crique-adolphe-2023-oct01-sca01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"sca"},{"etape_statut_id":"fav","is_brouillon":false,"date":"2023-01-11","id":"oXXG5ToIYbw8MvdYPX7sMMAP","ordre":11,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-crique-adolphe-2023-oct01-aca01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":null,"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"aca"},{"etape_statut_id":"fav","is_brouillon":false,"date":"2022-12-29","id":"y0SCXGJ1OBYSthcWyojyOLZX","ordre":8,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-crique-adolphe-2023-oct01-rde01","sections_with_values":[{"id":"deal","nom":"DEAL","elements":[{"id":"numero-dossier-deal-eau","nom":"Numéro de dossier","description":"Numéro de dossier DEAL Service eau","optionnel":true,"type":"text","value":""},{"id":"numero-recepisse","nom":"Numéro de récépissé","description":"Numéro de récépissé émis par la DEAL Service eau","optionnel":true,"type":"text","value":"R03-2022-12-29-00005"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"rde"},{"etape_statut_id":"fav","is_brouillon":false,"date":"2022-12-05","id":"0vdB4jaJbpIpyUnIZkKPsmCm","ordre":7,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-crique-adolphe-2023-oct01-mcr01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"mcr"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2022-11-08","id":"pF4UG6UrCOJmKjtgmtpwthTQ","ordre":4,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-crique-adolphe-2023-oct01-men01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"men"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2022-11-08","id":"pwqOEAsAmaWi0o24QiVeVZ40","ordre":3,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-crique-adolphe-2023-oct01-mfr01","sections_with_values":[{"id":"arm","nom":"Caractéristiques ARM","elements":[{"id":"mecanise","nom":"Prospection mécanisée","description":"","optionnel":false,"type":"radio","value":true},{"id":"franchissements","nom":"Franchissements de cours d'eau","description":"Nombre de franchissements de cours d'eau","optionnel":true,"type":"integer","value":12}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"demarches_consentement":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":4,"substances":["auru"],"titulaireIds":["fr-794312231"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.58181013905019,3.8309654861273],[-53.58178306390299,3.8219278216269807],[-53.572785590706495,3.82195493825841],[-53.57281257175149,3.8309926670647294],[-53.58181013905019,3.8309654861273]]],[[[-53.60031408473134,3.8224780986447566],[-53.59891645305842,3.8181831495446303],[-53.58181205656814,3.82379854768971],[-53.58320964990986,3.828093576227541],[-53.60031408473134,3.8224780986447566]]],[[[-53.583861926103765,3.8502114455117433],[-53.592379712320195,3.834289122043602],[-53.588417035915334,3.8321501920354253],[-53.57989914401643,3.8480725119510217],[-53.583861926103765,3.8502114455117433]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.58181013905019,3.8309654861273]},"properties":{"nom":"S1","description":"ARM1.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.57281257175149,3.8309926670647294]},"properties":{"nom":"S2","description":"ARM1.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.572785590706495,3.82195493825841]},"properties":{"nom":"S3","description":"ARM1.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.58178306390299,3.8219278216269807]},"properties":{"nom":"S4","description":"ARM1.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.60031408473134,3.8224780986447566]},"properties":{"nom":"S5","description":"ARM2.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.58320964990986,3.828093576227541]},"properties":{"nom":"S6","description":"ARM2.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.58181205656814,3.82379854768971]},"properties":{"nom":"S7","description":"ARM2.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.59891645305842,3.8181831495446303]},"properties":{"nom":"S8","description":"ARM2.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.583861926103765,3.8502114455117433]},"properties":{"nom":"S9","description":"ARM3.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.57989914401643,3.8480725119510217]},"properties":{"nom":"S10","description":"ARM3.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.588417035915334,3.8321501920354253]},"properties":{"nom":"S11","description":"ARM3.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.592379712320195,3.834289122043602]},"properties":{"nom":"S12","description":"ARM3.3"}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[213250,423875],[214250,423875],[214250,422875],[213250,422875],[213250,423875]]],[[[211190.6,422942.1],[213093.5,423557.7],[213247.4,423082],[211344.5,422466.4],[211190.6,422942.1]]],[[[213028.4,426005.2],[213468.1,425767.2],[212516.1,424008.3],[212076.4,424246.3],[213028.4,426005.2]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[213250,423875]},"properties":{"nom":"S1","description":"ARM1.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[214250,423875]},"properties":{"nom":"S2","description":"ARM1.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[214250,422875]},"properties":{"nom":"S3","description":"ARM1.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[213250,422875]},"properties":{"nom":"S4","description":"ARM1.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[211190.6,422942.1]},"properties":{"nom":"S5","description":"ARM2.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[213093.5,423557.7]},"properties":{"nom":"S6","description":"ARM2.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[213247.4,423082]},"properties":{"nom":"S7","description":"ARM2.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[211344.5,422466.4]},"properties":{"nom":"S8","description":"ARM2.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[213028.4,426005.2]},"properties":{"nom":"S9","description":"ARM3.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[213468.1,425767.2]},"properties":{"nom":"S10","description":"ARM3.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[212516.1,424008.3]},"properties":{"nom":"S11","description":"ARM3.3"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[212076.4,424246.3]},"properties":{"nom":"S12","description":"ARM3.3"}}]},"geojson_origine_geo_systeme_id":"2972","geojson4326_forages":null,"geojson_origine_forages":null,"surface":3,"communes":[{"id":"97353","nom":"Maripasoula"}],"secteurs_maritimes":[],"sdom_zones":[],"forets":[]}},"etape_type_id":"mfr","demarche_id_en_concurrence":null},{"etape_statut_id":"exe","is_brouillon":false,"date":"2022-09-26","id":"KA7tyvIdlqQmmVOuVjEl0Hdt","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-crique-adolphe-2023-oct01-dae01","sections_with_values":[{"id":"mea","nom":"Mission autorité environnementale","elements":[{"id":"arrete","nom":"Arrêté préfectoral","description":"Numéro de l'arrêté préfectoral portant décision dans le cadre de l'examen au cas par cas du projet d'autorisation de recherche minière","optionnel":true,"type":"text","value":"R03-2022-09-26-00002"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"dae"}],"demarche_type_id":"oct","demarche_statut_id":"acc","demarche_date_debut":"2023-09-19","demarche_date_fin":"2024-01-19","demarche_visibilite":"Publique","machine_id":"AncienLogigrammeOctroiARM","ordre":1}],"nb_activites_to_do":null}) criqueAdolpheData.nb_activites_to_do = 0 return Promise.resolve(criqueAdolpheData) @@ -459,7 +460,7 @@ const abattisKoticaApiClient: PropsApiClient = { getTitreAction(titreIdOrSlug) // prettier-ignore - const abattisData = titreGetValidator.parse({"id":"ooyCY2eGMXLunjmwPbBYyQcf","titre_visibilite":"Publique","nom":"Abattis Kotika","slug":"m-ar-abattis-kotika-2006","titre_type_id":"arm","titre_statut_id":"ech","titre_doublon":null,"references":[{"nom":"AR2006060","referenceTypeId":"onf"},{"nom":"2006-061","referenceTypeId":"ptm"}],"titre_last_modified_date":null,"demarches":[{"id":"SjKhYLXdqcla1BaN3nmgQhPs","demarche_visibilite":"Publique","slug":"m-ar-abattis-kotika-2006-oct01","description":null,"etapes":[{"etape_type_id":"def","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"acc","is_brouillon":false,"date":"2006-11-28","id":"Pw734o5mdB2K2AWaOKQ85Ydz","ordre":4,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-abattis-kotika-2006-oct01-def01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"sco","fondamentale":{"date_debut":null,"date_fin":"2007-03-27","duree":4,"substances":["auru"],"titulaireIds":["fr-480857036"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-54.256565011133,3.95310428827045],[-54.2571944444789,3.94846823388004],[-54.2392714613677,3.9464520807474],[-54.2387665564076,3.95076254570704],[-54.256565011133,3.95310428827045]]],[[[-54.251541223062,3.94479622927321],[-54.251001625524,3.94017377611083],[-54.2330489949186,3.94209562569541],[-54.2335613570663,3.94667311503072],[-54.251541223062,3.94479622927321]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-54.256565011133,3.95310428827045]},"properties":{"nom":"1","description":"a"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-54.2387665564076,3.95076254570704]},"properties":{"nom":"2","description":"b"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-54.2392714613677,3.9464520807474]},"properties":{"nom":"3","description":"c"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-54.2571944444789,3.94846823388004]},"properties":{"nom":"4","description":"d"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-54.251541223062,3.94479622927321]},"properties":{"nom":"1","description":"e"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-54.2335613570663,3.94667311503072]},"properties":{"nom":"2","description":"f"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-54.2330489949186,3.94209562569541]},"properties":{"nom":"3","description":"g"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-54.251001625524,3.94017377611083]},"properties":{"nom":"4","description":"h"}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[138288,437653],[140266,437386],[140208,436909],[138216,437140],[138288,437653]]],[[[138843,436731],[140843,436931],[140898,436424],[138901,436219],[138843,436731]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[138288,437653]},"properties":{"nom":"1","description":"a"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[140266,437386]},"properties":{"nom":"2","description":"b"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[140208,436909]},"properties":{"nom":"3","description":"c"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[138216,437140]},"properties":{"nom":"4","description":"d"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[138843,436731]},"properties":{"nom":"1","description":"e"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[140843,436931]},"properties":{"nom":"2","description":"f"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[140898,436424]},"properties":{"nom":"3","description":"g"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[138901,436219]},"properties":{"nom":"4","description":"h"}}]},"geojson_origine_geo_systeme_id":"2972","geojson4326_forages":null,"geojson_origine_forages":null,"surface":2,"communes":[{"id":"97362","nom":"Papaichton"}],"secteurs_maritimes":[],"sdom_zones":["0_potentielle","2"],"forets":[]}},"etape_statut_id":"fai","is_brouillon":false,"date":"2006-11-28","id":"1iF8kbcg0oGaEMAJxgUZYk8W","ordre":5,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-abattis-kotika-2006-oct01-sco01","sections_with_values":[{"id":"arm","nom":"Caractéristiques ARM","elements":[{"id":"mecanise","nom":"Prospection mécanisée","optionnel":false,"type":"radio","value":null}]},{"id":"suivi","nom":"Suivi de la démarche","elements":[{"id":"signataire","nom":"Signataire ONF","description":"Prénom et nom du représentant légal du titulaire de l'ONF","optionnel":true,"type":"text","value":"Michel Borderes"},{"id":"titulaire","nom":"Signataire titulaire","description":"Prénom et nom du représentant légal du titulaire de l'autorisation","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"men","etape_statut_id":"fai","is_brouillon":false,"date":"2006-10-16","id":"TMWQQo20x3j7BJ8Sboaq1B20","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-abattis-kotika-2006-oct01-men01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]}],"demarche_type_id":"oct","demarche_statut_id":"acc","demarche_date_debut":"2006-11-28","demarche_date_fin":"2007-03-27","ordre":1}],"nb_activites_to_do":null}) + const abattisData = titreGetValidator.parse({"id":"ooyCY2eGMXLunjmwPbBYyQcf","nom":"Abattis Kotika","slug":"m-ar-abattis-kotika-2006","titre_type_id":"arm","titre_statut_id":"ech","titre_visibilite":"Publique","titre_doublon":null,"references":[{"nom":"AR2006060","referenceTypeId":"onf"},{"nom":"2006-061","referenceTypeId":"ptm"}],"titre_last_modified_date":null,"demarches":[{"id":"SjKhYLXdqcla1BaN3nmgQhPs","slug":"m-ar-abattis-kotika-2006-oct01","description":null,"etapes":[{"etape_statut_id":"acc","is_brouillon":false,"date":"2006-11-28","id":"Pw734o5mdB2K2AWaOKQ85Ydz","ordre":4,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-abattis-kotika-2006-oct01-def01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"def"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2006-11-28","id":"1iF8kbcg0oGaEMAJxgUZYk8W","ordre":5,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-abattis-kotika-2006-oct01-sco01","sections_with_values":[{"id":"arm","nom":"Caractéristiques ARM","elements":[{"id":"mecanise","nom":"Prospection mécanisée","optionnel":false,"type":"radio","value":null}]},{"id":"suivi","nom":"Suivi de la démarche","elements":[{"id":"signataire","nom":"Signataire ONF","description":"Prénom et nom du représentant légal du titulaire de l'ONF","optionnel":true,"type":"text","value":"Michel Borderes"},{"id":"titulaire","nom":"Signataire titulaire","description":"Prénom et nom du représentant légal du titulaire de l'autorisation","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":"2007-03-27","duree":4,"substances":["auru"],"titulaireIds":["fr-480857036"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-54.256565011133,3.95310428827045],[-54.2571944444789,3.94846823388004],[-54.2392714613677,3.9464520807474],[-54.2387665564076,3.95076254570704],[-54.256565011133,3.95310428827045]]],[[[-54.251541223062,3.94479622927321],[-54.251001625524,3.94017377611083],[-54.2330489949186,3.94209562569541],[-54.2335613570663,3.94667311503072],[-54.251541223062,3.94479622927321]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-54.256565011133,3.95310428827045]},"properties":{"nom":"1","description":"a"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-54.2387665564076,3.95076254570704]},"properties":{"nom":"2","description":"b"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-54.2392714613677,3.9464520807474]},"properties":{"nom":"3","description":"c"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-54.2571944444789,3.94846823388004]},"properties":{"nom":"4","description":"d"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-54.251541223062,3.94479622927321]},"properties":{"nom":"1","description":"e"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-54.2335613570663,3.94667311503072]},"properties":{"nom":"2","description":"f"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-54.2330489949186,3.94209562569541]},"properties":{"nom":"3","description":"g"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-54.251001625524,3.94017377611083]},"properties":{"nom":"4","description":"h"}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[138288,437653],[140266,437386],[140208,436909],[138216,437140],[138288,437653]]],[[[138843,436731],[140843,436931],[140898,436424],[138901,436219],[138843,436731]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[138288,437653]},"properties":{"nom":"1","description":"a"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[140266,437386]},"properties":{"nom":"2","description":"b"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[140208,436909]},"properties":{"nom":"3","description":"c"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[138216,437140]},"properties":{"nom":"4","description":"d"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[138843,436731]},"properties":{"nom":"1","description":"e"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[140843,436931]},"properties":{"nom":"2","description":"f"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[140898,436424]},"properties":{"nom":"3","description":"g"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[138901,436219]},"properties":{"nom":"4","description":"h"}}]},"geojson_origine_geo_systeme_id":"2972","geojson4326_forages":null,"geojson_origine_forages":null,"surface":2,"communes":[{"id":"97362","nom":"Papaichton"}],"secteurs_maritimes":[],"sdom_zones":["0_potentielle","2"],"forets":[]}},"etape_type_id":"sco"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2006-10-16","id":"TMWQQo20x3j7BJ8Sboaq1B20","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-ar-abattis-kotika-2006-oct01-men01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"men"}],"demarche_type_id":"oct","demarche_statut_id":"acc","demarche_date_debut":"2006-11-28","demarche_date_fin":"2007-03-27","demarche_visibilite":"Publique","machine_id":null,"ordre":1}],"nb_activites_to_do":null}) abattisData.nb_activites_to_do = 0 return Promise.resolve(abattisData) @@ -485,16 +486,15 @@ const bonEspoirApiClient: PropsApiClient = { getTitreAction(titreIdOrSlug) // prettier-ignore - const bonEspoirData = titreGetValidator.parse({"id":"sJorD6pQomXTN7oRpyGwLijB","titre_visibilite":"Publique","nom":"Bon Espoir","slug":"m-pr-bon-espoir-2001","titre_type_id":"prm","titre_statut_id":"ech","titre_doublon":null,"references":[{"nom":"21/2001","referenceTypeId":"dea"},{"nom":"2013-0033-MI","referenceTypeId":"deb"}],"titre_last_modified_date":"2023-11-30","demarches":[{"id":"ry8fHgRWiKEOE1x1ZANmajh8","demarche_visibilite":"Publique","slug":"m-pr-bon-espoir-2001-oct01","description":null,"etapes":[{"etape_type_id":"dpu","fondamentale":{"date_debut":"2001-11-01","date_fin":null,"duree":60,"substances":["auru","scoc"],"titulaireIds":null,"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.9579321010744,5.07776938770113],[-53.9575232150351,4.98735333700249],[-53.8673626701318,4.98775355007457],[-53.8672265271601,4.95631734759459],[-53.7770631139658,4.95670276466037],[-53.7769878916108,4.93868722476635],[-53.5698730075868,4.93952315477954],[-53.5702069576163,5.02537608911083],[-53.759383911755,5.02460196044417],[-53.7596128864516,5.07864912381548],[-53.9579321010744,5.07776938770113]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9579321010744,5.07776938770113]},"properties":{"nom":"1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7596128864516,5.07864912381548]},"properties":{"nom":"2","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.759383911755,5.02460196044417]},"properties":{"nom":"3","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.5702069576163,5.02537608911083]},"properties":{"nom":"4","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.5698730075868,4.93952315477954]},"properties":{"nom":"5","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7769878916108,4.93868722476635]},"properties":{"nom":"6","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7770631139658,4.95670276466037]},"properties":{"nom":"7","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8672265271601,4.95631734759459]},"properties":{"nom":"8","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8673626701318,4.98775355007457]},"properties":{"nom":"9","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9575232150351,4.98735333700249]},"properties":{"nom":"10","description":null}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.957932101,5.077769388],[-53.957523215,4.987353337],[-53.86736267,4.98775355],[-53.867226527,4.956317348],[-53.777063114,4.956702765],[-53.776987892,4.938687225],[-53.569873008,4.939523155],[-53.570206958,5.025376089],[-53.759383912,5.02460196],[-53.759612886,5.078649124],[-53.957932101,5.077769388]]]]}},"geojson_origine_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9579321010744,5.07776938770113]},"properties":{"nom":"1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7596128864516,5.07864912381548]},"properties":{"nom":"2","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.759383911755,5.02460196044417]},"properties":{"nom":"3","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.5702069576163,5.02537608911083]},"properties":{"nom":"4","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.5698730075868,4.93952315477954]},"properties":{"nom":"5","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7769878916108,4.93868722476635]},"properties":{"nom":"6","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7770631139658,4.95670276466037]},"properties":{"nom":"7","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8672265271601,4.95631734759459]},"properties":{"nom":"8","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8673626701318,4.98775355007457]},"properties":{"nom":"9","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9575232150351,4.98735333700249]},"properties":{"nom":"10","description":null}}]},"geojson_origine_geo_systeme_id":"4326","geojson4326_forages":null,"geojson_origine_forages":null,"surface":465.5,"communes":[{"id":"97306","nom":"Mana"},{"id":"97311","nom":"Saint-Laurent-du-Maroni"}],"secteurs_maritimes":[],"sdom_zones":["0","2"],"forets":["LDD","MDF","PAUL"]}},"etape_statut_id":"fai","is_brouillon":false,"date":"2001-10-26","id":"CRVhvEIQAc319vUd8BfZoH5W","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-oct01-dpu01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":3201430},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":"EUR"}]},{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":false,"type":"text","value":"JORFTEXT000000774145"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"ECOI0100462D"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"dex","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"acc","is_brouillon":false,"date":"2001-10-24","id":"Ce4K8goEZzjqXRJLL051jcpD","ordre":1,"note":{"valeur":"Décret du 24 octobre 2001 accordant un permis de recherches A en Guyane","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-oct01-dex01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":null},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":null}]},{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":true,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]}],"demarche_type_id":"oct","demarche_statut_id":"acc","demarche_date_debut":"2001-11-01","demarche_date_fin":"2006-11-01","ordre":1},{"demarche_visibilite":"Publique","id":"PnFewl8P4Zt5Vm49zXqyn7Ml","slug":"m-pr-bon-espoir-2001-pr101","description":null,"etapes":[{"etape_type_id":"dpu","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["auru"],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"fai","is_brouillon":false,"date":"2010-03-02","id":"qtn2a3DNPx258VZgSjqXGKf6","ordre":4,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-pr101-dpu02","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":560000},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":"EUR"}]},{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":false,"type":"text","value":"JORFTEXT000021889053"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"DEVO1003938A"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"dex","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"acc","is_brouillon":false,"date":"2010-02-17","id":"tjOMgkb83wksMc6DFuqrecbu","ordre":3,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-pr101-dex02","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":null},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":null}]},{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":true,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[{"id":"2010-02-17-arr-a26ea089","type":"DESCRIPTION_OPTIONNELLE","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"arr","description":"Arrêté du 17 février 2010 modifiant l'arrêté du 6 mai 2009 prolongeant la validité du permis exclusif de recherches de mines d'or dit « Permis de Bon Espoir » et réduisant sa surface (Guyane)"}],"avis_documents":[]},{"etape_type_id":"dpu","fondamentale":{"date_debut":null,"date_fin":"2011-10-31","duree":null,"substances":["auru"],"titulaireIds":null,"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.9577777777778,5.07666666666667],[-53.9575,5.0325],[-53.8944444444444,5.00055555555556],[-53.8208333333333,4.97972222222222],[-53.7138888888889,4.96388888888889],[-53.7322222222222,5.02361111111111],[-53.8763888888889,5.02277777777778],[-53.9577777777778,5.07666666666667]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9577777777778,5.07666666666667]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8763888888889,5.02277777777778]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7322222222222,5.02361111111111]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7138888888889,4.96388888888889]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8208333333333,4.97972222222222]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8944444444444,5.00055555555556]},"properties":{"nom":"F","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9575,5.0325]},"properties":{"nom":"G","description":null}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.957777778,5.076666667],[-53.9575,5.0325],[-53.894444444,5.000555556],[-53.820833333,4.979722222],[-53.713888889,4.963888889],[-53.732222222,5.023611111],[-53.876388889,5.022777778],[-53.957777778,5.076666667]]]]}},"geojson_origine_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9577777777778,5.07666666666667]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8763888888889,5.02277777777778]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7322222222222,5.02361111111111]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7138888888889,4.96388888888889]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8208333333333,4.97972222222222]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8944444444444,5.00055555555556]},"properties":{"nom":"F","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9575,5.0325]},"properties":{"nom":"G","description":null}}]},"geojson_origine_geo_systeme_id":"4326","geojson4326_forages":null,"geojson_origine_forages":null,"surface":122.275,"communes":[{"id":"97306","nom":"Mana"},{"id":"97311","nom":"Saint-Laurent-du-Maroni"}],"secteurs_maritimes":[],"sdom_zones":["0","2"],"forets":["LDD","PAUL"]}},"etape_statut_id":"fai","is_brouillon":false,"date":"2009-05-16","id":"07cbyPCYcOtKYkw4kOqg2Sed","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-pr101-dpu01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":837000},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":"EUR"}]},{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":false,"type":"text","value":"JORFTEXT000020616467"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"DEVO0909004A"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"dex","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"acc","is_brouillon":false,"date":"2009-05-06","id":"orsPMmIfX4kSgVus0HTrBxAo","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-pr101-dex01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":null},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":null}]},{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":true,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[{"id":"2009-05-06-arr-54f88e41","type":"DESCRIPTION_OPTIONNELLE","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"arr","description":"Arrêté du 6 mai 2009 prolongeant la validité du permis exclusif de recherches de mines d'or dit « Permis Bon Espoir » et réduisant sa superficie (Guyane)"}],"avis_documents":[]}],"demarche_type_id":"pr1","demarche_statut_id":"acc","demarche_date_debut":"2006-11-01","demarche_date_fin":"2011-10-31","ordre":2},{"demarche_visibilite":"Publique","id":"EMFAv33wlGqMcjd6DwKzQBvr","slug":"m-pr-bon-espoir-2001-pr201","description":null,"etapes":[{"etape_type_id":"dpu","fondamentale":{"date_debut":null,"date_fin":"2016-10-31","duree":60,"substances":["auru","scoc"],"titulaireIds":["fr-401802863"],"amodiataireIds":null,"perimetre":null},"etape_statut_id":"fai","is_brouillon":false,"date":"2015-08-15","id":"Qp5DRYEN3Nc9n4CIwEYW7evs","ordre":9,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-pr201-dpu01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":1250000},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":"EUR"}]},{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":false,"type":"text","value":"JORFTEXT000031053068"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"EINL1518062A"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"dex","fondamentale":{"date_debut":null,"date_fin":null,"duree":60,"substances":["auru","scoc"],"titulaireIds":["fr-401802863"],"amodiataireIds":null,"perimetre":null},"etape_statut_id":"acc","is_brouillon":false,"date":"2015-08-03","id":"ABvgimvovFWeEhoMOrKi4wAy","ordre":8,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-pr201-dex01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":null},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":null}]},{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":true,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[{"id":"2015-08-03-arm-8bf71a65","type":"DESCRIPTION_OPTIONNELLE","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"arm","description":"Arrêté du 3 août 2015 prolongeant la durée de validité du permis exclusif de recherches de mines d'or et de substances connexes dit « Permis de Bon Espoir » attribué à la société Armina Ressources Minières dans le département de Guyane"}],"avis_documents":[]},{"etape_type_id":"men","etape_statut_id":"fai","is_brouillon":false,"date":"2011-06-30","id":"nLXaR7H78V43GB47ypDoqvKz","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-pr201-men01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"mfr", "demarche_id_en_concurrence": null, "demarches_consentement": [],"fondamentale":{"date_debut":null,"date_fin":null,"duree":60,"substances":["auru","arge","cuiv"],"titulaireIds":["fr-401802863"],"amodiataireIds":null,"perimetre":null},"etape_statut_id":"fai","is_brouillon":false,"date":"2011-06-29","id":"iV47juaOeL4EAUsOqiWN6gOO","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-pr201-mfr01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":null},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]}],"demarche_type_id":"pr2","demarche_statut_id":"acc","demarche_date_debut":"2011-10-31","demarche_date_fin":"2016-10-31","ordre":3}],"nb_activites_to_do":null}) + const bonEspoirData = titreGetValidator.parse({"id":"sJorD6pQomXTN7oRpyGwLijB","nom":"Bon Espoir","slug":"m-pr-bon-espoir-2001","titre_type_id":"prm","titre_statut_id":"ech","titre_visibilite":"Publique","titre_doublon":null,"references":[{"nom":"21/2001","referenceTypeId":"dea"},{"nom":"2013-0033-MI","referenceTypeId":"deb"}],"titre_last_modified_date":null,"demarches":[{"id":"ry8fHgRWiKEOE1x1ZANmajh8","slug":"m-pr-bon-espoir-2001-oct01","description":null,"etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"2001-10-26","id":"CRVhvEIQAc319vUd8BfZoH5W","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-oct01-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":"JORFTEXT000000774145"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"ECOI0100462D"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":"2001-11-01","date_fin":null,"duree":null,"substances":null,"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"2001-10-24","id":"Ce4K8goEZzjqXRJLL051jcpD","ordre":1,"note":{"valeur":"Décret du 24 octobre 2001 accordant un permis de recherches A en Guyane","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-oct01-dex01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":3201430},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":"EUR"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":60,"substances":["auru","scoc"],"titulaireIds":["fr-401802863"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.9579321010744,5.07776938770113],[-53.9575232150351,4.98735333700249],[-53.8673626701318,4.98775355007457],[-53.8672265271601,4.95631734759459],[-53.7770631139658,4.95670276466037],[-53.7769878916108,4.93868722476635],[-53.5698730075868,4.93952315477954],[-53.5702069576163,5.02537608911083],[-53.759383911755,5.02460196044417],[-53.7596128864516,5.07864912381548],[-53.9579321010744,5.07776938770113]]]]}},"geojson4326_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9579321010744,5.07776938770113]},"properties":{"nom":"1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7596128864516,5.07864912381548]},"properties":{"nom":"2","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.759383911755,5.02460196044417]},"properties":{"nom":"3","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.5702069576163,5.02537608911083]},"properties":{"nom":"4","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.5698730075868,4.93952315477954]},"properties":{"nom":"5","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7769878916108,4.93868722476635]},"properties":{"nom":"6","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7770631139658,4.95670276466037]},"properties":{"nom":"7","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8672265271601,4.95631734759459]},"properties":{"nom":"8","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8673626701318,4.98775355007457]},"properties":{"nom":"9","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9575232150351,4.98735333700249]},"properties":{"nom":"10","description":null}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.9579321010744,5.07776938770113],[-53.9575232150351,4.98735333700249],[-53.8673626701318,4.98775355007457],[-53.8672265271601,4.95631734759459],[-53.7770631139658,4.95670276466037],[-53.7769878916108,4.93868722476635],[-53.5698730075868,4.93952315477954],[-53.5702069576163,5.02537608911083],[-53.759383911755,5.02460196044417],[-53.7596128864516,5.07864912381548],[-53.9579321010744,5.07776938770113]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9579321010744,5.07776938770113]},"properties":{"nom":"1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7596128864516,5.07864912381548]},"properties":{"nom":"2","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.759383911755,5.02460196044417]},"properties":{"nom":"3","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.5702069576163,5.02537608911083]},"properties":{"nom":"4","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.5698730075868,4.93952315477954]},"properties":{"nom":"5","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7769878916108,4.93868722476635]},"properties":{"nom":"6","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7770631139658,4.95670276466037]},"properties":{"nom":"7","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8672265271601,4.95631734759459]},"properties":{"nom":"8","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8673626701318,4.98775355007457]},"properties":{"nom":"9","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9575232150351,4.98735333700249]},"properties":{"nom":"10","description":null}}]},"geojson_origine_geo_systeme_id":"4326","geojson4326_forages":null,"geojson_origine_forages":null,"surface":464.71,"communes":[{"id":"97306","nom":"Mana"},{"id":"97311","nom":"Saint-Laurent-du-Maroni"}],"secteurs_maritimes":[],"sdom_zones":["0","2"],"forets":["LDD","MDF","PAUL"]}},"etape_type_id":"dex"}],"demarche_type_id":"oct","demarche_statut_id":"acc","demarche_date_debut":"2001-11-01","demarche_date_fin":"2006-11-01","demarche_visibilite":"Publique","machine_id":null,"ordre":1},{"id":"PnFewl8P4Zt5Vm49zXqyn7Ml","slug":"m-pr-bon-espoir-2001-pr101","description":null,"etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"2010-03-02","id":"qtn2a3DNPx258VZgSjqXGKf6","ordre":4,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-pr101-dpu02","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":560000},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":"EUR"}]},{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":"JORFTEXT000021889053"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"DEVO1003938A"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["auru"],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"2010-02-17","id":"tjOMgkb83wksMc6DFuqrecbu","ordre":3,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-pr101-dex02","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":null},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":null}]}],"entreprises_documents":[],"etape_documents":[{"type":"DESCRIPTION_OPTIONNELLE","id":"2010-02-17-arr-a26ea089","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"arr","description":"Arrêté du 17 février 2010 modifiant l'arrêté du 6 mai 2009 prolongeant la validité du permis exclusif de recherches de mines d'or dit « Permis de Bon Espoir » et réduisant sa surface (Guyane)"}],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dex"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2009-05-16","id":"07cbyPCYcOtKYkw4kOqg2Sed","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-pr101-dpu01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":837000},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":"EUR"}]},{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":"JORFTEXT000020616467"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"DEVO0909004A"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":"2011-10-31","duree":null,"substances":["auru"],"titulaireIds":null,"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.9577777777778,5.07666666666667],[-53.9575,5.0325],[-53.8944444444444,5.00055555555556],[-53.8208333333333,4.97972222222222],[-53.7138888888889,4.96388888888889],[-53.7322222222222,5.02361111111111],[-53.8763888888889,5.02277777777778],[-53.9577777777778,5.07666666666667]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9577777777778,5.07666666666667]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8763888888889,5.02277777777778]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7322222222222,5.02361111111111]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7138888888889,4.96388888888889]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8208333333333,4.97972222222222]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8944444444444,5.00055555555556]},"properties":{"nom":"F","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9575,5.0325]},"properties":{"nom":"G","description":null}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.9577777777778,5.07666666666667],[-53.9575,5.0325],[-53.8944444444444,5.00055555555556],[-53.8208333333333,4.97972222222222],[-53.7138888888889,4.96388888888889],[-53.7322222222222,5.02361111111111],[-53.8763888888889,5.02277777777778],[-53.9577777777778,5.07666666666667]]]]}},"geojson_origine_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9577777777778,5.07666666666667]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8763888888889,5.02277777777778]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7322222222222,5.02361111111111]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7138888888889,4.96388888888889]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8208333333333,4.97972222222222]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8944444444444,5.00055555555556]},"properties":{"nom":"F","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9575,5.0325]},"properties":{"nom":"G","description":null}}]},"geojson_origine_geo_systeme_id":"4326","geojson4326_forages":null,"geojson_origine_forages":null,"surface":122.275,"communes":[{"id":"97306","nom":"Mana"},{"id":"97311","nom":"Saint-Laurent-du-Maroni"}],"secteurs_maritimes":[],"sdom_zones":["0","2"],"forets":["LDD","PAUL"]}},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"2009-05-06","id":"orsPMmIfX4kSgVus0HTrBxAo","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-pr101-dex01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":null},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":null}]}],"entreprises_documents":[],"etape_documents":[{"type":"DESCRIPTION_OPTIONNELLE","id":"2009-05-06-arr-54f88e41","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"arr","description":"Arrêté du 6 mai 2009 prolongeant la validité du permis exclusif de recherches de mines d'or dit « Permis Bon Espoir » et réduisant sa superficie (Guyane)"}],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dex"}],"demarche_type_id":"pr1","demarche_statut_id":"acc","demarche_date_debut":"2006-11-01","demarche_date_fin":"2011-10-31","demarche_visibilite":"Publique","machine_id":null,"ordre":2},{"id":"EMFAv33wlGqMcjd6DwKzQBvr","slug":"m-pr-bon-espoir-2001-pr201","description":null,"etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"2015-08-15","id":"Qp5DRYEN3Nc9n4CIwEYW7evs","ordre":10,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-pr201-dpu01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":1250000},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":"EUR"}]},{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":"JORFTEXT000031053068"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"EINL1518062A"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":"2016-10-31","duree":60,"substances":["auru","scoc"],"titulaireIds":["fr-401802863"],"amodiataireIds":null,"perimetre":null},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"2015-08-03","id":"ABvgimvovFWeEhoMOrKi4wAy","ordre":9,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-pr201-dex01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":null},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":null}]}],"entreprises_documents":[],"etape_documents":[{"type":"DESCRIPTION_OPTIONNELLE","id":"2015-08-03-arm-8bf71a65","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"arm","description":"Arrêté du 3 août 2015 prolongeant la durée de validité du permis exclusif de recherches de mines d'or et de substances connexes dit « Permis de Bon Espoir » attribué à la société Armina Ressources Minières dans le département de Guyane"}],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":60,"substances":["auru","scoc"],"titulaireIds":["fr-401802863"],"amodiataireIds":null,"perimetre":null},"etape_type_id":"dex"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2011-06-30","id":"nLXaR7H78V43GB47ypDoqvKz","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-pr201-men01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"men"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2011-06-29","id":"iV47juaOeL4EAUsOqiWN6gOO","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-bon-espoir-2001-pr201-mfr01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":null},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"demarches_consentement":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":60,"substances":["auru","arge","cuiv"],"titulaireIds":["fr-401802863"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.9577777777778,5.07666666666667],[-53.9575,5.0325],[-53.8944444444444,5.00055555555556],[-53.8208333333333,4.97972222222222],[-53.7138888888889,4.96388888888889],[-53.7322222222222,5.02361111111111],[-53.8763888888889,5.02277777777778],[-53.9577777777778,5.07666666666667]]]]}},"geojson4326_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9577777777778,5.07666666666667]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8763888888889,5.02277777777778]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7322222222222,5.02361111111111]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7138888888889,4.96388888888889]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8208333333333,4.97972222222222]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8944444444444,5.00055555555556]},"properties":{"nom":"F","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9575,5.0325]},"properties":{"nom":"G","description":null}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.9577777777778,5.07666666666667],[-53.9575,5.0325],[-53.8944444444444,5.00055555555556],[-53.8208333333333,4.97972222222222],[-53.7138888888889,4.96388888888889],[-53.7322222222222,5.02361111111111],[-53.8763888888889,5.02277777777778],[-53.9577777777778,5.07666666666667]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9577777777778,5.07666666666667]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8763888888889,5.02277777777778]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7322222222222,5.02361111111111]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.7138888888889,4.96388888888889]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8208333333333,4.97972222222222]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.8944444444444,5.00055555555556]},"properties":{"nom":"F","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.9575,5.0325]},"properties":{"nom":"G","description":null}}]},"geojson_origine_geo_systeme_id":"4326","geojson4326_forages":null,"geojson_origine_forages":null,"surface":122.14,"communes":[{"id":"97306","nom":"Mana"},{"id":"97311","nom":"Saint-Laurent-du-Maroni"}],"secteurs_maritimes":[],"sdom_zones":["0","2"],"forets":["LDD","PAUL"]}},"etape_type_id":"mfr","demarche_id_en_concurrence":null}],"demarche_type_id":"pr2","demarche_statut_id":"acc","demarche_date_debut":"2011-10-31","demarche_date_fin":"2016-10-31","demarche_visibilite":"Publique","machine_id":null,"ordre":3}],"nb_activites_to_do":null}) bonEspoirData.nb_activites_to_do = 0 // prettier-ignore - bonEspoirData.demarches.push(demarcheGetValidator.parse({"demarche_visibilite":"Publique", - "id": "idtravaux", "ordre": 4, "slug": "m-pr-bon-espoir-2001-dam01", "description": null, "etapes": [{ "etape_type_id": "wpo", "is_brouillon": false, "ordre": 4, note: {valeur: '', is_avertissement: false}, "etape_statut_id": "acc", "date": "2012-07-23", "id": "idEtapeTravaux1", "slug": "m-pr-bon-espoir-2001-dam01-wpo01", "sections_with_values": [], "entreprises_documents": [], "avis_documents": [], "etape_documents": [{ "id": "2012-07-23-apd-607c3aa8","type":"DESCRIPTION_OPTIONNELLE", "description": "N°2012-SPR-DRMSS-1", "etape_document_type_id": "apd", "public_lecture": false, "entreprises_lecture": false }] }, { "etape_type_id": "wpp", is_brouillon: ETAPE_IS_NOT_BROUILLON, "ordre": 3, note: { valeur: 'note importante', is_avertissement: true },"etape_statut_id": "fai","date": "2011-05-04","id": "idEtapeTravaux2","slug": "m-pr-bon-espoir-2001-dam01-wpp01","sections_with_values": [],"entreprises_documents": [],"avis_documents":[],"etape_documents": [{"id": "id_Document","type":"DESCRIPTION_OPTIONNELLE","description": "","etape_document_type_id": "apu","public_lecture": false,"entreprises_lecture": false }]}, {"etape_type_id": "wfd",is_brouillon: ETAPE_IS_NOT_BROUILLON, "ordre": 2,note: {valeur: '', is_avertissement: false}, "etape_statut_id": "fai","date": "2010-10-01","id": "idEtapeTravaux3","slug": "m-pr-bon-espoir-2001-dam01-wfd01","sections_with_values": [],"entreprises_documents": [],"etape_documents": [],"avis_documents":[]}, {"etape_type_id": "mcr",is_brouillon: ETAPE_IS_NOT_BROUILLON,"ordre": 1,note: {valeur: '', is_avertissement: false},"etape_statut_id": "fav","date": "2010-10-01","id": "idEtapeTravaux4","slug": "m-pr-bon-espoir-2001-dam01-mcr01","sections_with_values": [],"entreprises_documents": [],"etape_documents": [],"avis_documents":[]}],"demarche_type_id": "dam","demarche_statut_id": "fpm","demarche_date_debut": null,"demarche_date_fin": null - + bonEspoirData.demarches.push(demarcheGetValidator.parse({ + 'demarche_visibilite':"Publique","machine_id":null,"id": "idtravaux", "ordre": 4, "slug": "m-pr-bon-espoir-2001-dam01", "description": null, "etapes": [{ "etape_type_id": "wpo", "is_brouillon": false, "ordre": 4, note: {valeur: '', is_avertissement: false}, "etape_statut_id": "acc", "date": "2012-07-23", "id": "idEtapeTravaux1", "slug": "m-pr-bon-espoir-2001-dam01-wpo01", "sections_with_values": [], "entreprises_documents": [], "avis_documents": [], "etape_documents": [{ "id": "2012-07-23-apd-607c3aa8","type":"DESCRIPTION_OPTIONNELLE", "description": "N°2012-SPR-DRMSS-1", "etape_document_type_id": "apd", "public_lecture": false, "entreprises_lecture": false }] }, { "etape_type_id": "wpp", is_brouillon: ETAPE_IS_NOT_BROUILLON, "ordre": 3, note: { valeur: 'note importante', is_avertissement: true },"etape_statut_id": "fai","date": "2011-05-04","id": "idEtapeTravaux2","slug": "m-pr-bon-espoir-2001-dam01-wpp01","sections_with_values": [],"entreprises_documents": [],"avis_documents":[],"etape_documents": [{"id": "id_Document","type":"DESCRIPTION_OPTIONNELLE","description": "","etape_document_type_id": "apu","public_lecture": false,"entreprises_lecture": false }]}, {"etape_type_id": "wfd",is_brouillon: ETAPE_IS_NOT_BROUILLON, "ordre": 2,note: {valeur: '', is_avertissement: false}, "etape_statut_id": "fai","date": "2010-10-01","id": "idEtapeTravaux3","slug": "m-pr-bon-espoir-2001-dam01-wfd01","sections_with_values": [],"entreprises_documents": [],"etape_documents": [],"avis_documents":[]}, {"etape_type_id": "mcr",is_brouillon: ETAPE_IS_NOT_BROUILLON,"ordre": 1,note: {valeur: '', is_avertissement: false},"etape_statut_id": "fav","date": "2010-10-01","id": "idEtapeTravaux4","slug": "m-pr-bon-espoir-2001-dam01-mcr01","sections_with_values": [],"entreprises_documents": [],"etape_documents": [],"avis_documents":[]}],"demarche_type_id": "dam","demarche_statut_id": "fpm","demarche_date_debut": null,"demarche_date_fin": null })) // prettier-ignore - bonEspoirData.demarches.push(demarcheGetValidator.parse({"demarche_visibilite":"Publique","id":"KxHulLhT5XtziPhZDWpFuyA9", "ordre": 5, "slug":"m-pr-bon-espoir-2001-vct01","description":null,"etapes":[{"etape_type_id":"mcr",is_brouillon: ETAPE_IS_NOT_BROUILLON,"etape_statut_id":"fav","date":"2017-08-07","id":"OOKaEetpmAhDX17hcLEFWTZ1","ordre":4,note: {valeur: '', is_avertissement: false},"slug":"m-pr-bon-espoir-2001-vct01-mcr01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"men",is_brouillon: ETAPE_IS_NOT_BROUILLON,"etape_statut_id":"fai","date":"2016-11-07","id":"fNt0G9CmdMc6iIG9x239wZ5E","ordre":2,note: {valeur: '', is_avertissement: false},"slug":"m-pr-bon-espoir-2001-vct01-men01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"mfr", "demarche_id_en_concurrence": null, "demarches_consentement": [],is_brouillon: ETAPE_IS_NOT_BROUILLON,"fondamentale":{"date_debut":null,"date_fin":null,"duree":180,"substances":["auru","scoc"],"titulaireIds":["fr-401802863"],"amodiataireIds":null,"perimetre":{"geojson4326_points": null,"geojson4326_forages":null,"geojson_origine_forages":null,"geojson_origine_points": null, "geojson4326_perimetre":{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[-53.95781742722346,5.076877972864504],[-53.95761604147164,5.032517695391918],[-53.894654620091046,5.000735152488521],[-53.82094960753945,4.97999409410299],[-53.71414492282594,4.963998224562106],[-53.73241245985785,5.023653513799631],[-53.87657715038456,5.023033474690702],[-53.95781742722346,5.076877972864504]]]]},"properties":null}, "geojson_origine_perimetre":{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[-53.95781742722346,5.076877972864504],[-53.95761604147164,5.032517695391918],[-53.894654620091046,5.000735152488521],[-53.82094960753945,4.97999409410299],[-53.71414492282594,4.963998224562106],[-53.73241245985785,5.023653513799631],[-53.87657715038456,5.023033474690702],[-53.95781742722346,5.076877972864504]]]]},"properties":null},"geojson_origine_geo_systeme_id":"4326","surface":122.275,"communes":[{"id":"97311","nom":"Saint-Laurent-du-Maroni"},{"id":"97306","nom":"Mana"}],"secteurs_maritimes":[],"sdom_zones":["0","2"],"forets":["LDD","PAUL"]}},"etape_statut_id":"fai","date":"2016-10-28","id":"VqBn5DzAtcMQWFY0CIiO6X1A","ordre":1,note: {valeur: '', is_avertissement: false},"slug":"m-pr-bon-espoir-2001-vct01-mfr01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":null},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":null}]}],"entreprises_documents":[],"etape_documents":[], "avis_documents":[]}],"demarche_type_id":"vct","demarche_statut_id":"ins","demarche_date_debut":"2016-10-31","demarche_date_fin":null})) + bonEspoirData.demarches.push(demarcheGetValidator.parse({'demarche_visibilite':"Publique","machine_id":null,"id":"KxHulLhT5XtziPhZDWpFuyA9", "ordre": 5, "slug":"m-pr-bon-espoir-2001-vct01","description":null,"etapes":[{"etape_type_id":"mcr",is_brouillon: ETAPE_IS_NOT_BROUILLON,"etape_statut_id":"fav","date":"2017-08-07","id":"OOKaEetpmAhDX17hcLEFWTZ1","ordre":4,note: {valeur: '', is_avertissement: false},"slug":"m-pr-bon-espoir-2001-vct01-mcr01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"men",is_brouillon: ETAPE_IS_NOT_BROUILLON,"etape_statut_id":"fai","date":"2016-11-07","id":"fNt0G9CmdMc6iIG9x239wZ5E","ordre":2,note: {valeur: '', is_avertissement: false},"slug":"m-pr-bon-espoir-2001-vct01-men01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"mfr", "demarche_id_en_concurrence": null, "demarches_consentement": [],is_brouillon: ETAPE_IS_NOT_BROUILLON,"fondamentale":{"date_debut":null,"date_fin":null,"duree":180,"substances":["auru","scoc"],"titulaireIds":["fr-401802863"],"amodiataireIds":null,"perimetre":{"geojson4326_points": null,"geojson4326_forages":null,"geojson_origine_forages":null,"geojson_origine_points": null, "geojson4326_perimetre":{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[-53.95781742722346,5.076877972864504],[-53.95761604147164,5.032517695391918],[-53.894654620091046,5.000735152488521],[-53.82094960753945,4.97999409410299],[-53.71414492282594,4.963998224562106],[-53.73241245985785,5.023653513799631],[-53.87657715038456,5.023033474690702],[-53.95781742722346,5.076877972864504]]]]},"properties":null}, "geojson_origine_perimetre":{"type":"Feature","geometry":{"type":"MultiPolygon","coordinates":[[[[-53.95781742722346,5.076877972864504],[-53.95761604147164,5.032517695391918],[-53.894654620091046,5.000735152488521],[-53.82094960753945,4.97999409410299],[-53.71414492282594,4.963998224562106],[-53.73241245985785,5.023653513799631],[-53.87657715038456,5.023033474690702],[-53.95781742722346,5.076877972864504]]]]},"properties":null},"geojson_origine_geo_systeme_id":"4326","surface":122.275,"communes":[{"id":"97311","nom":"Saint-Laurent-du-Maroni"},{"id":"97306","nom":"Mana"}],"secteurs_maritimes":[],"sdom_zones":["0","2"],"forets":["LDD","PAUL"]}},"etape_statut_id":"fai","date":"2016-10-28","id":"VqBn5DzAtcMQWFY0CIiO6X1A","ordre":1,note: {valeur: '', is_avertissement: false},"slug":"m-pr-bon-espoir-2001-vct01-mfr01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":null},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":null}]}],"entreprises_documents":[],"etape_documents":[], "avis_documents":[]}],"demarche_type_id":"vct","demarche_statut_id":"ins","demarche_date_debut":"2016-10-31","demarche_date_fin":null})) return Promise.resolve(bonEspoirData) }, @@ -545,7 +545,7 @@ const basseManaApiClient: PropsApiClient = { getTitreAction(titreIdOrSlug) // prettier-ignore - const basseManaData = titreGetValidator.parse({ "id": "ORKjSbwrb87xE53MsYClV8OF","titre_visibilite":"Publique", "nom": "Basse Mana", "slug": "m-pr-basse-mana-2018", "titre_type_id": "prm", "titre_statut_id": "sup", "titre_doublon": null, "references": [{ "nom": "22/2018", "referenceTypeId": "dea" }, { "nom": "2016-0010-MI", "referenceTypeId": "deb" }], "titre_last_modified_date": "2023-12-19", "demarches": [{"demarche_visibilite":"Publique", "id": "GnIerujOWqlS3U06Xcbc1Dr0", "slug": "m-pr-basse-mana-2018-oct01", "description": null, "etapes": [{ "etape_type_id": "dpu", "fondamentale": { "date_debut": null, "date_fin": null, "duree": 36, "substances": ["tant", "niob", "lith", "bery", "etai", "wolf", "tita", "auru"], "titulaireIds": ["fr-790856850"], "amodiataireIds": null, "perimetre": { "geojson4326_perimetre": { "type": "Feature", "properties": {}, "geometry": { "type": "MultiPolygon", "coordinates": [[[[-53.699125239725, 5.29137675727333], [-53.735659753333, 5.24333287037071], [-53.6847736578144, 5.232646225266], [-53.664223513371, 5.23752353831223], [-53.6554344678131, 5.25034817283726], [-53.6402449164671, 5.25044876137938], [-53.6331053301638, 5.26979119871868], [-53.6650166925488, 5.27353207619541], [-53.699125239725, 5.29137675727333]]]] } }, "geojson4326_points": { "type": "FeatureCollection", "properties": {}, "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [-53.699125239725, 5.29137675727333] }, "properties": { "nom": "A", "description": null } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-53.6650166925488, 5.27353207619541] }, "properties": { "nom": "B", "description": null } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-53.6331053301638, 5.26979119871868] }, "properties": { "nom": "C", "description": null } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-53.6402449164671, 5.25044876137938] }, "properties": { "nom": "D", "description": null } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-53.6554344678131, 5.25034817283726] }, "properties": { "nom": "E", "description": null } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-53.664223513371, 5.23752353831223] }, "properties": { "nom": "F", "description": null } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-53.6847736578144, 5.232646225266] }, "properties": { "nom": "G", "description": null } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-53.735659753333, 5.24333287037071] }, "properties": { "nom": "H", "description": null } }] }, "geojson_origine_perimetre": { "type": "Feature", "properties": {}, "geometry": { "type": "MultiPolygon", "coordinates": [[[[200814, 585525], [204589, 583534], [208127, 583105], [207326, 580968], [205641, 580964], [204660, 579549], [202378, 579019], [196738, 580226], [200814, 585525]]]] } }, "geojson_origine_points": { "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [200814, 585525] }, "properties": { "nom": "A" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [204589, 583534] }, "properties": { "nom": "B" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [208127, 583105] }, "properties": { "nom": "C" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [207326, 580968] }, "properties": { "nom": "D" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [205641, 580964] }, "properties": { "nom": "E" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [204660, 579549] }, "properties": { "nom": "F" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [202378, 579019] }, "properties": { "nom": "G" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [196738, 580226] }, "properties": { "nom": "H" } }] }, "geojson_origine_geo_systeme_id": "2972", "geojson4326_forages": null, "geojson_origine_forages": null, "surface": 48, "communes": [{ "id": "97306", "nom": "Mana" }], "secteurs_maritimes": [], "sdom_zones": ["2"], "forets": ["BSM"] } }, "etape_statut_id": "fai", "is_brouillon": false, "date": "2018-09-11", "id": "ooH6ZbECJPcDPFsE0McnKvUm", "ordre": 9, "note": { "valeur": "", "is_avertissement": false }, "slug": "m-pr-basse-mana-2018-oct01-dpu01", "sections_with_values": [{ "id": "prx", "nom": "Propriétés du permis exclusif de recherches", "elements": [{ "id": "engagement", "nom": "Engagement", "optionnel": true, "type": "number", "value": 150000 }, { "id": "engagementDeviseId", "nom": "Devise de l'engagement", "description": "", "optionnel": true, "type": "select", "options": [{ "id": "EUR", "nom": "Euros" }, { "id": "FRF", "nom": "Francs" }, { "id": "XPF", "nom": "Francs Pacifique" }], "value": "EUR" }] }, { "id": "publication", "nom": "Références Légifrance", "elements": [{ "id": "jorf", "nom": "Numéro JORF", "description": "", "optionnel": false, "type": "text", "value": "JORFTEXT000037382008" }, { "id": "nor", "nom": "Numéro NOR", "description": "", "optionnel": true, "type": "text", "value": "ECOL1816264A" }] }], "entreprises_documents": [], "etape_documents": [], "avis_documents": [] }, { "etape_type_id": "dex", "fondamentale": { "date_debut": null, "date_fin": null, "duree": 36, "substances": ["tant", "niob", "lith", "bery", "etai", "wolf", "tita", "auru"], "titulaireIds": ["fr-790856850"], "amodiataireIds": null, "perimetre": { "geojson4326_perimetre": { "type": "Feature", "properties": {}, "geometry": { "type": "MultiPolygon", "coordinates": [[[[-53.699125239725, 5.29137675727333], [-53.735659753333, 5.24333287037071], [-53.6847736578144, 5.232646225266], [-53.664223513371, 5.23752353831223], [-53.6554344678131, 5.25034817283726], [-53.6402449164671, 5.25044876137938], [-53.6331053301638, 5.26979119871868], [-53.6650166925488, 5.27353207619541], [-53.699125239725, 5.29137675727333]]]] } }, "geojson4326_points": { "type": "FeatureCollection", "properties": {}, "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [-53.699125239725, 5.29137675727333] }, "properties": { "nom": "A", "description": null } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-53.6650166925488, 5.27353207619541] }, "properties": { "nom": "B", "description": null } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-53.6331053301638, 5.26979119871868] }, "properties": { "nom": "C", "description": null } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-53.6402449164671, 5.25044876137938] }, "properties": { "nom": "D", "description": null } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-53.6554344678131, 5.25034817283726] }, "properties": { "nom": "E", "description": null } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-53.664223513371, 5.23752353831223] }, "properties": { "nom": "F", "description": null } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-53.6847736578144, 5.232646225266] }, "properties": { "nom": "G", "description": null } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [-53.735659753333, 5.24333287037071] }, "properties": { "nom": "H", "description": null } }] }, "geojson_origine_perimetre": { "type": "Feature", "properties": {}, "geometry": { "type": "MultiPolygon", "coordinates": [[[[200814, 585525], [204589, 583534], [208127, 583105], [207326, 580968], [205641, 580964], [204660, 579549], [202378, 579019], [196738, 580226], [200814, 585525]]]] } }, "geojson_origine_points": { "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [200814, 585525] }, "properties": { "nom": "A" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [204589, 583534] }, "properties": { "nom": "B" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [208127, 583105] }, "properties": { "nom": "C" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [207326, 580968] }, "properties": { "nom": "D" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [205641, 580964] }, "properties": { "nom": "E" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [204660, 579549] }, "properties": { "nom": "F" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [202378, 579019] }, "properties": { "nom": "G" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [196738, 580226] }, "properties": { "nom": "H" } }] }, "geojson_origine_geo_systeme_id": "2972", "geojson4326_forages": null, "geojson_origine_forages": null, "surface": 48, "communes": [{ "id": "97306", "nom": "Mana" }], "secteurs_maritimes": [], "sdom_zones": ["2"], "forets": ["BSM"] } }, "etape_statut_id": "acc", "is_brouillon": false, "date": "2018-08-31", "id": "KJtV68vswF5ewUyF2jTuLGhS", "ordre": 8, "note": { "valeur": "", "is_avertissement": false }, "slug": "m-pr-basse-mana-2018-oct01-dex01", "sections_with_values": [{ "id": "prx", "nom": "Propriétés du permis exclusif de recherches", "elements": [{ "id": "engagement", "nom": "Engagement", "optionnel": true, "type": "number", "value": 150000 }, { "id": "engagementDeviseId", "nom": "Devise de l'engagement", "description": "", "optionnel": true, "type": "select", "options": [{ "id": "EUR", "nom": "Euros" }, { "id": "FRF", "nom": "Francs" }, { "id": "XPF", "nom": "Francs Pacifique" }], "value": "EUR" }] }, { "id": "publication", "nom": "Références Légifrance", "elements": [{ "id": "jorf", "nom": "Numéro JORF", "description": "", "optionnel": true, "type": "text", "value": "JORFTEXT000037382008" }, { "id": "nor", "nom": "Numéro NOR", "description": "", "optionnel": true, "type": "text", "value": "ECOL1816264A" }] }], "entreprises_documents": [], "etape_documents": [], "avis_documents": [] }, { "etape_type_id": "men", "etape_statut_id": "fai", "is_brouillon": false, "date": "2016-08-28", "id": "qVJM9zS6hWyIr3My5OoubQA3", "ordre": 2, "note": { "valeur": "", "is_avertissement": false }, "slug": "m-pr-basse-mana-2018-oct01-men01", "sections_with_values": [], "entreprises_documents": [], "etape_documents": [], "avis_documents": [] }, { "etape_type_id": "mfr", "demarche_id_en_concurrence": null, "demarches_consentement": [], "fondamentale": { "date_debut": null, "date_fin": null, "duree": 36, "substances": ["tant", "niob", "scoc"], "titulaireIds": null, "amodiataireIds": null, "perimetre": null }, "etape_statut_id": "fai", "is_brouillon": false, "date": "2016-06-19", "id": "abABihashClZP0lL3NUPELNV", "ordre": 1, "note": { "valeur": "", "is_avertissement": false }, "slug": "m-pr-basse-mana-2018-oct01-mfr01", "sections_with_values": [{ "id": "prx", "nom": "Propriétés du permis exclusif de recherches", "elements": [{ "id": "engagement", "nom": "Engagement", "optionnel": true, "type": "number", "value": null }, { "id": "engagementDeviseId", "nom": "Devise de l'engagement", "description": "", "optionnel": true, "type": "select", "options": [{ "id": "EUR", "nom": "Euros" }, { "id": "FRF", "nom": "Francs" }, { "id": "XPF", "nom": "Francs Pacifique" }], "value": null }] }], "entreprises_documents": [], "etape_documents": [], "avis_documents": [] }], "demarche_type_id": "oct", "demarche_statut_id": "acc", "demarche_date_debut": "2018-09-11", "demarche_date_fin": "2021-09-11", "ordre": 1 }, {"demarche_visibilite":"Publique", "id": "mZAUVvPyznbzpj3e3grjFmlJ", "slug": "m-pr-basse-mana-2018-pr101", "description": null, "etapes": [{ "etape_type_id": "rpu", "fondamentale": { "date_debut": null, "date_fin": null, "duree": null, "substances": null, "titulaireIds": null, "amodiataireIds": null, "perimetre": null }, "etape_statut_id": "fai", "is_brouillon": false, "date": "2023-11-17", "id": "f76c17ab21ca966988390d92", "ordre": 11, "note": { "valeur": "", "is_avertissement": false }, "slug": "m-pr-basse-mana-2018-pr101-rpu01", "sections_with_values": [], "entreprises_documents": [], "etape_documents": [], "avis_documents": [] }, { "etape_type_id": "dpu", "fondamentale": { "date_debut": null, "date_fin": null, "duree": null, "substances": null, "titulaireIds": null, "amodiataireIds": null, "perimetre": null }, "etape_statut_id": "fai", "is_brouillon": false, "date": "2023-11-15", "id": "71f6497117b21325d53d8e56", "ordre": 10, "note": { "valeur": "", "is_avertissement": false }, "slug": "m-pr-basse-mana-2018-pr101-dpu01", "sections_with_values": [{ "id": "publication", "nom": "Références Légifrance", "elements": [{ "id": "jorf", "nom": "Numéro JORF", "description": "", "optionnel": false, "type": "text", "value": "Texte 3 sur 160" }] }], "entreprises_documents": [], "etape_documents": [{ "id": "2023-11-15-pub-4d420801", "type": "DESCRIPTION_OPTIONNELLE", "public_lecture": true, "entreprises_lecture": true, "etape_document_type_id": "pub", "description": "" }], "avis_documents": [] }, { "etape_type_id": "dex", "fondamentale": { "date_debut": null, "date_fin": null, "duree": 30, "substances": null, "titulaireIds": null, "amodiataireIds": null, "perimetre": null }, "etape_statut_id": "acc", "is_brouillon": false, "date": "2023-11-07", "id": "590f6dd2f808eeadf51b820e", "ordre": 9, "note": { "valeur": "", "is_avertissement": false }, "slug": "m-pr-basse-mana-2018-pr101-dex01", "sections_with_values": [{ "id": "publication", "nom": "Références Légifrance", "elements": [{ "id": "jorf", "nom": "Numéro JORF", "description": "", "optionnel": true, "type": "text", "value": null }, { "id": "nor", "nom": "Numéro NOR", "description": "", "optionnel": true, "type": "text", "value": null }] }], "entreprises_documents": [], "etape_documents": [], "avis_documents": [] }, { "etape_type_id": "ppu", "etape_statut_id": "ter", "is_brouillon": false, "date": "2023-03-27", "id": "M1mK0vhAHH5CTaUwq4cJzK49", "ordre": 5, "note": { "valeur": "", "is_avertissement": false }, "slug": "m-pr-basse-mana-2018-pr101-ppu01", "sections_with_values": [{ "id": "opdp", "elements": [{ "id": "lien", "nom": "Lien public externe", "description": "", "optionnel": true, "type": "url", "value": null }, {"id": "duree", "nom": "Durée en jours de la consultation du public", "description": "", "optionnel": false, "type": "number", "value": 15}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"men","etape_statut_id":"fai","is_brouillon":false,"date":"2021-04-30","id":"wFb34sxGyHoRNOByPffQZyAF","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-pr101-men01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"mfr", "demarche_id_en_concurrence": null, "demarches_consentement": [],"fondamentale":{"date_debut":null,"date_fin":null,"duree":60,"substances":["tant","niob","lith","bery","etai","wolf","tita","auru"],"titulaireIds":["fr-790856850"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.699150462397206,5.291394409468797],[-53.73568497160258,5.2433505257409125],[-53.684798879087204,5.232663883719148],[-53.664248736219285,5.2375411971227654],[-53.65545969176547,5.250365830767107],[-53.64027014144058,5.250466419912988],[-53.633130556393525,5.269808855679936],[-53.66511918689031,5.291623119512839],[-53.699150462397206,5.291394409468797]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.699150462397206,5.291394409468797]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.66511918689031,5.291623119512839]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.633130556393525,5.269808855679936]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.64027014144058,5.250466419912988]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.65545969176547,5.250365830767107]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.664248736219285,5.2375411971227654]},"properties":{"nom":"F","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.684798879087204,5.232663883719148]},"properties":{"nom":"G","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.73568497160258,5.2433505257409125]},"properties":{"nom":"H","description":null}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[200814,585525],[204589,585534],[208127,583105],[207326,580968],[205641,580964],[204660,579549],[202378,579019],[196738,580226],[200814,585525]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[200814,585525]},"properties":{"nom":"A"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[204589,585534]},"properties":{"nom":"B"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[208127,583105]},"properties":{"nom":"C"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[207326,580968]},"properties":{"nom":"D"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[205641,580964]},"properties":{"nom":"E"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[204660,579549]},"properties":{"nom":"F"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[202378,579019]},"properties":{"nom":"G"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[196738,580226]},"properties":{"nom":"H"}}]},"geojson_origine_geo_systeme_id":"2972","geojson4326_forages":null,"geojson_origine_forages":null,"surface":48.06,"communes":[{"id":"97306","nom":"Mana"}],"secteurs_maritimes":[],"sdom_zones":["2"],"forets":["BSM"]}},"etape_statut_id":"fai","is_brouillon":false,"date":"2021-04-30","id":"NKW0jIKc5cPBIp2dwu2VceCG","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-pr101-mfr01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":null},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]}],"demarche_type_id":"pr1","demarche_statut_id":"acc","demarche_date_debut":"2021-09-11","demarche_date_fin":"2024-03-11","ordre":2},{"demarche_visibilite":"Publique","id":"5df48d3536a38dd1dab542d7","slug":"m-pr-basse-mana-2018-pr201","description":"","etapes":[{"etape_type_id":"men","etape_statut_id":"fai","is_brouillon":false,"date":"2023-10-30","id":"37a1752da216067fc73328f9","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-pr201-men01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"mfr", "demarche_id_en_concurrence": null, "demarches_consentement": [],"fondamentale":{"date_debut":null,"date_fin":null,"duree":60,"substances":["tant","niob","lith","bery","etai","wolf","tita","auru"],"titulaireIds":null,"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.695977302723314,5.258026897118486],[-53.69166175320614,5.243894120712839],[-53.691207934852734,5.238962048893827],[-53.66947244758239,5.236434510036549],[-53.66426676493007,5.2375411203489115],[-53.655468706369525,5.250365792413383],[-53.64027010339901,5.25045738302719],[-53.63422022259896,5.267391338838475],[-53.64933956522329,5.274005464773927],[-53.66943759690406,5.2748050575845875],[-53.66988205803166,5.281761503749559],[-53.671594626284566,5.281690874443703],[-53.67432345044184,5.276844434310086],[-53.67742349010169,5.274481516415551],[-53.68523182828244,5.270616251350751],[-53.695977302723314,5.258026897118486]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.695977302723314,5.258026897118486]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.68523182828244,5.270616251350751]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.67742349010169,5.274481516415551]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.67432345044184,5.276844434310086]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.671594626284566,5.281690874443703]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.66988205803166,5.281761503749559]},"properties":{"nom":"F","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.66943759690406,5.2748050575845875]},"properties":{"nom":"G","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.64933956522329,5.274005464773927]},"properties":{"nom":"H","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.63422022259896,5.267391338838475]},"properties":{"nom":"I","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.64027010339901,5.25045738302719]},"properties":{"nom":"J","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.655468706369525,5.250365792413383]},"properties":{"nom":"K","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.66426676493007,5.2375411203489115]},"properties":{"nom":"L","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.66947244758239,5.236434510036549]},"properties":{"nom":"M","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.691207934852734,5.238962048893827]},"properties":{"nom":"N","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.69166175320614,5.243894120712839]},"properties":{"nom":"O","description":null}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[201150,581831],[202348,583219],[203216,583643],[203561,583903],[203866,584438],[204056,584445],[204102,583675],[206331,583577],[208005,582838],[207326,580967],[205640,580964],[204658,579549],[204080,579429],[201670,579719],[201622,580265],[201150,581831]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[201150,581831]},"properties":{"nom":"A"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[202348,583219]},"properties":{"nom":"B"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[203216,583643]},"properties":{"nom":"C"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[203561,583903]},"properties":{"nom":"D"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[203866,584438]},"properties":{"nom":"E"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[204056,584445]},"properties":{"nom":"F"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[204102,583675]},"properties":{"nom":"G"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[206331,583577]},"properties":{"nom":"H"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[208005,582838]},"properties":{"nom":"I"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[207326,580967]},"properties":{"nom":"J"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[205640,580964]},"properties":{"nom":"K"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[204658,579549]},"properties":{"nom":"L"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[204080,579429]},"properties":{"nom":"M"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[201670,579719]},"properties":{"nom":"N"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[201622,580265]},"properties":{"nom":"O"}}]},"geojson_origine_geo_systeme_id":"2972","geojson4326_forages":null,"geojson_origine_forages":null,"surface":20.69,"communes":[{"id":"97306","nom":"Mana"}],"secteurs_maritimes":[],"sdom_zones":["2"],"forets":["BSM"]}},"etape_statut_id":"fai","is_brouillon":false,"date":"2023-10-30","id":"47a22a6ca44891d40e2f4149","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-pr201-mfr01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":null},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]}],"demarche_type_id":"pr2","demarche_statut_id":"dep","demarche_date_debut":"2024-03-11","demarche_date_fin":null,"ordre":3}],"nb_activites_to_do":null}) + const basseManaData = titreGetValidator.parse({"id":"ORKjSbwrb87xE53MsYClV8OF","nom":"Basse Mana","slug":"m-pr-basse-mana-2018","titre_type_id":"prm","titre_statut_id":"sup","titre_visibilite":"Publique","titre_doublon":null,"references":[{"nom":"22/2018","referenceTypeId":"dea"},{"nom":"2016-0010-MI","referenceTypeId":"deb"},{"nom":"R16-08","referenceTypeId":"dea"},{"nom":"R23-02","referenceTypeId":"dea"}],"titre_last_modified_date":null,"demarches":[{"id":"GnIerujOWqlS3U06Xcbc1Dr0","slug":"m-pr-basse-mana-2018-oct01","description":null,"etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"2018-09-11","id":"ooH6ZbECJPcDPFsE0McnKvUm","ordre":9,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-oct01-dpu01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":150000},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":"EUR"}]},{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":"JORFTEXT000037382008"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"ECOL1816264A"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":36,"substances":["tant","niob","lith","bery","etai","wolf","tita","auru"],"titulaireIds":["fr-790856850"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.699125239725,5.29137675727333],[-53.735659753333,5.24333287037071],[-53.6847736578144,5.232646225266],[-53.664223513371,5.23752353831223],[-53.6554344678131,5.25034817283726],[-53.6402449164671,5.25044876137938],[-53.6331053301638,5.26979119871868],[-53.6650166925488,5.27353207619541],[-53.699125239725,5.29137675727333]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.699125239725,5.29137675727333]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.6650166925488,5.27353207619541]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.6331053301638,5.26979119871868]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.6402449164671,5.25044876137938]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.6554344678131,5.25034817283726]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.664223513371,5.23752353831223]},"properties":{"nom":"F","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.6847736578144,5.232646225266]},"properties":{"nom":"G","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.735659753333,5.24333287037071]},"properties":{"nom":"H","description":null}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[200814,585525],[204589,583534],[208127,583105],[207326,580968],[205641,580964],[204660,579549],[202378,579019],[196738,580226],[200814,585525]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[200814,585525]},"properties":{"nom":"A"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[204589,583534]},"properties":{"nom":"B"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[208127,583105]},"properties":{"nom":"C"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[207326,580968]},"properties":{"nom":"D"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[205641,580964]},"properties":{"nom":"E"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[204660,579549]},"properties":{"nom":"F"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[202378,579019]},"properties":{"nom":"G"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[196738,580226]},"properties":{"nom":"H"}}]},"geojson_origine_geo_systeme_id":"2972","geojson4326_forages":null,"geojson_origine_forages":null,"surface":48,"communes":[{"id":"97306","nom":"Mana"}],"secteurs_maritimes":[],"sdom_zones":["2"],"forets":["BSM"]}},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"2018-08-31","id":"KJtV68vswF5ewUyF2jTuLGhS","ordre":8,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-oct01-dex01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":150000},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":"EUR"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":36,"substances":["tant","niob","lith","bery","etai","wolf","tita","auru"],"titulaireIds":["fr-790856850"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.699125239725,5.29137675727333],[-53.735659753333,5.24333287037071],[-53.6847736578144,5.232646225266],[-53.664223513371,5.23752353831223],[-53.6554344678131,5.25034817283726],[-53.6402449164671,5.25044876137938],[-53.6331053301638,5.26979119871868],[-53.6650166925488,5.27353207619541],[-53.699125239725,5.29137675727333]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.699125239725,5.29137675727333]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.6650166925488,5.27353207619541]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.6331053301638,5.26979119871868]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.6402449164671,5.25044876137938]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.6554344678131,5.25034817283726]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.664223513371,5.23752353831223]},"properties":{"nom":"F","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.6847736578144,5.232646225266]},"properties":{"nom":"G","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.735659753333,5.24333287037071]},"properties":{"nom":"H","description":null}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[200814,585525],[204589,583534],[208127,583105],[207326,580968],[205641,580964],[204660,579549],[202378,579019],[196738,580226],[200814,585525]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[200814,585525]},"properties":{"nom":"A"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[204589,583534]},"properties":{"nom":"B"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[208127,583105]},"properties":{"nom":"C"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[207326,580968]},"properties":{"nom":"D"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[205641,580964]},"properties":{"nom":"E"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[204660,579549]},"properties":{"nom":"F"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[202378,579019]},"properties":{"nom":"G"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[196738,580226]},"properties":{"nom":"H"}}]},"geojson_origine_geo_systeme_id":"2972","geojson4326_forages":null,"geojson_origine_forages":null,"surface":48,"communes":[{"id":"97306","nom":"Mana"}],"secteurs_maritimes":[],"sdom_zones":["2"],"forets":["BSM"]}},"etape_type_id":"dex"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2016-08-28","id":"qVJM9zS6hWyIr3My5OoubQA3","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-oct01-men01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"men"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2016-06-19","id":"abABihashClZP0lL3NUPELNV","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-oct01-mfr01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":null},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"demarches_consentement":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":36,"substances":["tant","niob","scoc"],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"mfr","demarche_id_en_concurrence":null}],"demarche_type_id":"oct","demarche_statut_id":"acc","demarche_date_debut":"2018-09-11","demarche_date_fin":"2021-09-11","demarche_visibilite":"Publique","machine_id":null,"ordre":1},{"id":"mZAUVvPyznbzpj3e3grjFmlJ","slug":"m-pr-basse-mana-2018-pr101","description":null,"etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"2023-11-17","id":"f76c17ab21ca966988390d92","ordre":9,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-pr101-rpu01","sections_with_values":[{"id":"praa","nom":"Propriétés de la publication","elements":[{"id":"numeroRAA","nom":"Numéro de RAA ","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":null,"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"rpu"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2023-11-15","id":"71f6497117b21325d53d8e56","ordre":8,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-pr101-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":"Texte 3 sur 160"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[{"type":"DESCRIPTION_OPTIONNELLE","id":"2023-11-15-pub-4d420801","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"pub","description":""}],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":null,"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"2023-11-07","id":"590f6dd2f808eeadf51b820e","ordre":7,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-pr101-dex01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":30,"substances":null,"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dex"},{"etape_statut_id":"ter","is_brouillon":false,"date":"2023-03-27","id":"M1mK0vhAHH5CTaUwq4cJzK49","ordre":5,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-pr101-ppu01","sections_with_values":[{"id":"opdp","elements":[{"id":"lien","nom":"Lien public externe","description":"","optionnel":true,"type":"url","value":null},{"id":"duree","nom":"Durée en jours de la consultation du public","optionnel":false,"type":"number","value":18}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"ppu"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2021-04-30","id":"NKW0jIKc5cPBIp2dwu2VceCG","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-pr101-mfr01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":null},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"demarches_consentement":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":60,"substances":["tant","niob","lith","bery","etai","wolf","tita","auru"],"titulaireIds":["fr-790856850"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.699150462397206,5.291394409468797],[-53.73568497160258,5.2433505257409125],[-53.684798879087204,5.232663883719148],[-53.664248736219285,5.2375411971227654],[-53.65545969176547,5.250365830767107],[-53.64027014144058,5.250466419912988],[-53.633130556393525,5.269808855679936],[-53.66511918689031,5.291623119512839],[-53.699150462397206,5.291394409468797]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.699150462397206,5.291394409468797]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.66511918689031,5.291623119512839]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.633130556393525,5.269808855679936]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.64027014144058,5.250466419912988]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.65545969176547,5.250365830767107]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.664248736219285,5.2375411971227654]},"properties":{"nom":"F","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.684798879087204,5.232663883719148]},"properties":{"nom":"G","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.73568497160258,5.2433505257409125]},"properties":{"nom":"H","description":null}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[200814,585525],[204589,585534],[208127,583105],[207326,580968],[205641,580964],[204660,579549],[202378,579019],[196738,580226],[200814,585525]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[200814,585525]},"properties":{"nom":"A"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[204589,585534]},"properties":{"nom":"B"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[208127,583105]},"properties":{"nom":"C"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[207326,580968]},"properties":{"nom":"D"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[205641,580964]},"properties":{"nom":"E"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[204660,579549]},"properties":{"nom":"F"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[202378,579019]},"properties":{"nom":"G"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[196738,580226]},"properties":{"nom":"H"}}]},"geojson_origine_geo_systeme_id":"2972","geojson4326_forages":null,"geojson_origine_forages":null,"surface":48.06,"communes":[{"id":"97306","nom":"Mana"}],"secteurs_maritimes":[],"sdom_zones":["2"],"forets":["BSM"]}},"etape_type_id":"mfr","demarche_id_en_concurrence":null},{"etape_statut_id":"fai","is_brouillon":false,"date":"2021-04-30","id":"wFb34sxGyHoRNOByPffQZyAF","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-pr101-men01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"men"}],"demarche_type_id":"pr1","demarche_statut_id":"acc","demarche_date_debut":"2021-09-11","demarche_date_fin":"2024-03-11","demarche_visibilite":"Publique","machine_id":null,"ordre":2},{"id":"5df48d3536a38dd1dab542d7","slug":"m-pr-basse-mana-2018-pr201","description":"","etapes":[{"etape_statut_id":"fav","is_brouillon":false,"date":"2024-05-17","id":"e72a53fdb3bdffacf1f4fdef","ordre":5,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-pr201-mcr01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"mcr"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2023-10-30","id":"37a1752da216067fc73328f9","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-pr201-men01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"men"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2023-10-30","id":"47a22a6ca44891d40e2f4149","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-pr-basse-mana-2018-pr201-mfr01","sections_with_values":[{"id":"prx","nom":"Propriétés du permis exclusif de recherches","elements":[{"id":"engagement","nom":"Engagement","optionnel":true,"type":"number","value":null},{"id":"engagementDeviseId","nom":"Devise de l'engagement","description":"","optionnel":true,"type":"select","options":[{"id":"EUR","nom":"Euros"},{"id":"FRF","nom":"Francs"},{"id":"XPF","nom":"Francs Pacifique"}],"value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"demarches_consentement":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":60,"substances":["tant","niob","lith","bery","etai","wolf","tita","auru"],"titulaireIds":null,"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[-53.695977302723314,5.258026897118486],[-53.69166175320614,5.243894120712839],[-53.691207934852734,5.238962048893827],[-53.66947244758239,5.236434510036549],[-53.66426676493007,5.2375411203489115],[-53.655468706369525,5.250365792413383],[-53.64027010339901,5.25045738302719],[-53.63422022259896,5.267391338838475],[-53.64933956522329,5.274005464773927],[-53.66943759690406,5.2748050575845875],[-53.66988205803166,5.281761503749559],[-53.671594626284566,5.281690874443703],[-53.67432345044184,5.276844434310086],[-53.67742349010169,5.274481516415551],[-53.68523182828244,5.270616251350751],[-53.695977302723314,5.258026897118486]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.695977302723314,5.258026897118486]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.68523182828244,5.270616251350751]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.67742349010169,5.274481516415551]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.67432345044184,5.276844434310086]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.671594626284566,5.281690874443703]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.66988205803166,5.281761503749559]},"properties":{"nom":"F","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.66943759690406,5.2748050575845875]},"properties":{"nom":"G","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.64933956522329,5.274005464773927]},"properties":{"nom":"H","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.63422022259896,5.267391338838475]},"properties":{"nom":"I","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.64027010339901,5.25045738302719]},"properties":{"nom":"J","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.655468706369525,5.250365792413383]},"properties":{"nom":"K","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.66426676493007,5.2375411203489115]},"properties":{"nom":"L","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.66947244758239,5.236434510036549]},"properties":{"nom":"M","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.691207934852734,5.238962048893827]},"properties":{"nom":"N","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[-53.69166175320614,5.243894120712839]},"properties":{"nom":"O","description":null}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[201150,581831],[202348,583219],[203216,583643],[203561,583903],[203866,584438],[204056,584445],[204102,583675],[206331,583577],[208005,582838],[207326,580967],[205640,580964],[204658,579549],[204080,579429],[201670,579719],[201622,580265],[201150,581831]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[201150,581831]},"properties":{"nom":"A"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[202348,583219]},"properties":{"nom":"B"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[203216,583643]},"properties":{"nom":"C"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[203561,583903]},"properties":{"nom":"D"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[203866,584438]},"properties":{"nom":"E"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[204056,584445]},"properties":{"nom":"F"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[204102,583675]},"properties":{"nom":"G"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[206331,583577]},"properties":{"nom":"H"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[208005,582838]},"properties":{"nom":"I"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[207326,580967]},"properties":{"nom":"J"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[205640,580964]},"properties":{"nom":"K"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[204658,579549]},"properties":{"nom":"L"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[204080,579429]},"properties":{"nom":"M"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[201670,579719]},"properties":{"nom":"N"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[201622,580265]},"properties":{"nom":"O"}}]},"geojson_origine_geo_systeme_id":"2972","geojson4326_forages":null,"geojson_origine_forages":null,"surface":20.69,"communes":[{"id":"97306","nom":"Mana"}],"secteurs_maritimes":[],"sdom_zones":["2"],"forets":["BSM"]}},"etape_type_id":"mfr","demarche_id_en_concurrence":null}],"demarche_type_id":"pr2","demarche_statut_id":"ins","demarche_date_debut":"2024-03-11","demarche_date_fin":null,"demarche_visibilite":"Publique","machine_id":null,"ordre":3}],"nb_activites_to_do":null}) return Promise.resolve(basseManaData) }, @@ -736,7 +736,7 @@ const lenoncourtApiClient: PropsApiClient = { getTitreAction(titreIdOrSlug) // prettier-ignore - const lenoncourtData = titreGetValidator.parse({"id":"s7RvqvCAgKs4DxkQBYV93cVx","titre_visibilite":"Publique","nom":"Lenoncourt","slug":"m-cx-lenoncourt-1968","titre_type_id":"cxm","titre_statut_id":"val","titre_doublon":null,"references":[{"nom":"2013-0275-MI","referenceTypeId":"deb"},{"nom":"54TM0153","referenceTypeId":"rnt"}],"titre_last_modified_date":"2024-03-21","demarches":[{"demarche_visibilite":"Publique","id":"ozYnUjy40eru81jUnXz5snv2","slug":"m-cx-lenoncourt-1968-oct01","description":null,"etapes":[{"etape_type_id":"dpu","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["nacl"],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"fai","is_brouillon":false,"date":"1968-01-24","id":"SG2zAN9QaKBN1hZKqKEgQGpI","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-oct01-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":false,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[{"id":"1968-01-24-dec-89a94bb2","type":"DESCRIPTION_OPTIONNELLE","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"dec","description":"Décret du 13 janvier 1968 instituant la concession de mines de sels de sodium de Lenoncourt (Meurthe-et-Moselle) au profit de la société Les Soudières réunies - La Madeleine-Varangéville"}],"avis_documents":[]},{"etape_type_id":"dex","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"acc","is_brouillon":false,"date":"1968-01-13","id":"LM2Zk3PwAjrduc4EqmucOjeB","ordre":1,"note":{"valeur":"Décret du 13 janvier 1968 instituant la concession de mines de sels de sodium de Lenoncourt (Meurthe-et-Moselle) au profit de la société Les Soudières réunies - La Madeleine-Varangéville","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-oct01-dex01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":true,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]}],"demarche_type_id":"oct","demarche_statut_id":"acc","demarche_date_debut":"1968-01-24","demarche_date_fin":"2024-03-01","ordre":1},{"demarche_visibilite":"Publique","id":"wM0cpipWSef9lDAHDurJxxhk","slug":"m-cx-lenoncourt-1968-mut01","description":null,"etapes":[{"etape_type_id":"dpu","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["selg","selh"],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"fai","is_brouillon":false,"date":"1970-11-19","id":"XScxzwDKFxmYtDnkJ7X7qZBi","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut01-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":false,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[{"id":"1970-11-19-dec-8a77b142","type":"DESCRIPTION_OPTIONNELLE","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"dec","description":"Décret du 16 novembre 1970 autorisant la mutation de propriété de cinq concessions de mines de sel gemme et de sources salées au profit de la société Produits chimiques Pechlney-Saint-Gobaln."}],"avis_documents":[]},{"etape_type_id":"dex","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":["fr-606320471"],"amodiataireIds":null,"perimetre":null},"etape_statut_id":"acc","is_brouillon":false,"date":"1970-11-16","id":"ejAqTpzBj82jgF0ShiwMRQmW","ordre":1,"note":{"valeur":"Décret du 16 novembre 1970 autorisant la mutation de propriété de cinq concessions de mines de sel gemme et de sources salées au profit de la société Produits chimiques Pechlney-Saint-Gobaln.","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut01-dex01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":true,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]}],"demarche_type_id":"mut","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"ordre":2},{"demarche_visibilite":"Publique","id":"1UC2b0ORsm2ezCh6whHzbOKR","slug":"m-cx-lenoncourt-1968-mut02","description":null,"etapes":[{"etape_type_id":"dpu","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["selg","selh"],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"fai","is_brouillon":false,"date":"1975-11-27","id":"TjimKkEETzF0yGBG2m085on9","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut02-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":false,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[{"id":"1975-11-27-dec-b50a06f5","type":"DESCRIPTION_OPTIONNELLE","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"dec","description":"Décret du 24 novembre 1975 autorisant la mutation de cinq concessions de mines de sel gemme et de sources salées au profit de la Compagnie industrielle et minière"}],"avis_documents":[]},{"etape_type_id":"dex","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":["fr-712025048"],"amodiataireIds":null,"perimetre":null},"etape_statut_id":"acc","is_brouillon":false,"date":"1975-11-24","id":"aYO0zwBFBOZP7VN11JaJDhzI","ordre":1,"note":{"valeur":"Décret du 24 novembre 1975 autorisant la mutation de cinq concessions de mines de sel gemme et de sources salées au profit de la Compagnie industrielle et minière","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut02-dex01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":true,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]}],"demarche_type_id":"mut","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"ordre":3},{"demarche_visibilite":"Publique","id":"H5eANAZPKhY9eFQtCyLYjCvp","slug":"m-cx-lenoncourt-1968-exp01","description":null,"etapes":[{"etape_type_id":"dpu","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["nacl"],"titulaireIds":["fr-712025048"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[6.275644095814427,48.6854960696669],[6.255874124806144,48.675237870291575],[6.295319143383101,48.66801114312286],[6.316241924966296,48.676189123934925],[6.315656943097024,48.680413137182065],[6.307671761547864,48.69027442550079],[6.302487495007789,48.68919858322589],[6.296317613859298,48.68917495187758],[6.290997693817669,48.68780534512822],[6.285653764289864,48.68913324659737],[6.281744418990354,48.68911774206666],[6.275644095814427,48.6854960696669]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[6.275644095814427,48.6854960696669]},"properties":{"nom":"A","description":"Point situé sur la ligne joignant les clochers de Saulxures-lès-Nancy et de Buissoncourt, à son intersection avec la limite des communes de Saulxures-lès-Nancy et de Lenoncourt, soit à environ 2040 mètres à l'Est-Sud-Est du clocher de Saulxures-lès-Nancy"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.281744418990354,48.68911774206666]},"properties":{"nom":"B1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.285653764289864,48.68913324659737]},"properties":{"nom":"C1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.290997693817669,48.68780534512822]},"properties":{"nom":"D1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.296317613859298,48.68917495187758]},"properties":{"nom":"E1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.302487495007789,48.68919858322589]},"properties":{"nom":"F1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.307671761547864,48.69027442550079]},"properties":{"nom":"G1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.315656943097024,48.680413137182065]},"properties":{"nom":"B","description":"Point situé sur la ligne joignant les clochers de Saulxures-lès-Nancy et de Buissoncourt, à son intersection avec la limite Ouest de la concession de Cercueil-Buissoncourt, soit à environ 2 150 mètres au Nord-Nord-Ouest du clocher de Buissoncourt"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.316241924966296,48.676189123934925]},"properties":{"nom":"C","description":"Borne commune aux concessions d'Art-sur-Meurthe et de Cercueil-Buissoncourt"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.295319143383101,48.66801114312286]},"properties":{"nom":"D","description":"Sommet A de la concession d'Art-sur-Meurthe:"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.255874124806144,48.675237870291575]},"properties":{"nom":"E","description":"Sommet M de la concession d'Art-sur•Meurthe:"}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[889907.42,1117010.26],[890334.9,1117435.93],[890622.24,1117452.72],[891022.89,1117325.88],[891406.04,1117498.53],[891859.53,1117525.03],[892234.39,1117664.59],[892879.34,1116600.52],[892947.15,1116133.73],[891456.2,1115144.46],[888513.03,1115795.21],[889907.42,1117010.26]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[889907.42,1117010.26]},"properties":{"nom":"A","description":"Point situé sur la ligne joignant les clochers de Saulxures-lès-Nancy et de Buissoncourt, à son intersection avec la limite des communes de Saulxures-lès-Nancy et de Lenoncourt, soit à environ 2040 mètres à l’Est-Sud-Est du clocher de Saulxures-lès-Nancy"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[890334.9,1117435.93]},"properties":{"nom":"B1"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[890622.24,1117452.72]},"properties":{"nom":"C1"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[891022.89,1117325.88]},"properties":{"nom":"D1"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[891406.04,1117498.53]},"properties":{"nom":"E1"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[891859.53,1117525.03]},"properties":{"nom":"F1"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[892234.39,1117664.59]},"properties":{"nom":"G1"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[892879.34,1116600.52]},"properties":{"nom":"B","description":"Point situé sur la ligne joignant les clochers de Saulxures-lès-Nancy et de Buissoncourt, à son intersection avec la limite Ouest de la concession de Cercueil-Buissoncourt, soit à environ 2 150 mètres au Nord-Nord-Ouest du clocher de Buissoncourt"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[892947.15,1116133.73]},"properties":{"nom":"C","description":"Borne commune aux concessions d’Art-sur-Meurthe et de Cercueil-Buissoncourt"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[891456.2,1115144.46]},"properties":{"nom":"D","description":"Sommet A de la concession d’Art-sur-Meurthe:"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[888513.03,1115795.21]},"properties":{"nom":"E","description":"Sommet M de la concession d’Art-sur•Meurthe:"}}]},"geojson_origine_geo_systeme_id":"27571","geojson4326_forages":null,"geojson_origine_forages":null,"surface":6.75,"communes":[{"id":"54495","nom":"Saulxures-lès-Nancy"},{"id":"54311","nom":"Lenoncourt"},{"id":"54110","nom":"Cerville"},{"id":"54025","nom":"Art-sur-Meurthe"}],"secteurs_maritimes":[],"sdom_zones":[],"forets":[]}},"etape_statut_id":"fai","is_brouillon":false,"date":"1981-09-13","id":"C6UHWZDSFnLbwuaeksXG1SEj","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-exp01-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":false,"type":"text","value":"N"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[{"id":"1981-09-13-dec-8bf8fa4c","type":"DESCRIPTION_OPTIONNELLE","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"dec","description":"Décret du 9 septembre 1981 portant extension de superficie de la concession des mines de sels de sodium de Lenoncourt (Meurthe-et-Moselle) et modifiant les conditions auxquelles est soumise ladite concession"}],"avis_documents":[]},{"etape_type_id":"dex","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"acc","is_brouillon":false,"date":"1981-09-09","id":"xHxKuYk5goClAaZr1hxGaCyr","ordre":1,"note":{"valeur":"Décret du 9 septembre 1981 portant extension de superficie de la concession des mines de sels de sodium de Lenoncourt (Meurthe-et-Moselle) et modifiant les conditions auxquelles est soumise ladite concession","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-exp01-dex01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":true,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]}],"demarche_type_id":"exp","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"ordre":4},{"demarche_visibilite":"Publique","id":"W9IX7VanFA5iYxYAGulcA0CY","slug":"m-cx-lenoncourt-1968-mut03","description":null,"etapes":[{"etape_type_id":"dpu","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["nacl"],"titulaireIds":["fr-442993283"],"amodiataireIds":null,"perimetre":null},"etape_statut_id":"fai","is_brouillon":false,"date":"2000-10-06","id":"wuYTEAQ5UUAUZxiowQIthgkg","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut03-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":false,"type":"text","value":"JORFTEXT000000208330"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"ECOI0000456A"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"dex","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"acc","is_brouillon":false,"date":"2000-09-26","id":"f2iSnn7XPrOXDIrbmYFKUiz1","ordre":1,"note":{"valeur":"Arrêté du 26 septembre 2000 autorisant la mutation de concessions de mines","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut03-dex01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":true,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]}],"demarche_type_id":"mut","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"ordre":6},{"demarche_visibilite":"Publique","id":"md9yLbhZSOqdcOANAAyUPTur","slug":"m-cx-lenoncourt-1968-mut04","description":null,"etapes":[{"etape_type_id":"dpu","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["nacl"],"titulaireIds":["fr-642014526"],"amodiataireIds":null,"perimetre":null},"etape_statut_id":"fai","is_brouillon":false,"date":"2003-01-08","id":"yuMPprDNtN6mZzdmlVTDd25I","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut04-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":false,"type":"text","value":"JORFTEXT000000228627"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"INDI0200856A"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"dex","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"acc","is_brouillon":false,"date":"2002-12-24","id":"jZRW7aZo5DmTABnQCe35wVrh","ordre":1,"note":{"valeur":"Arrêté du 24 décembre 2002 autorisant la mutation de concessions de mines","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut04-dex01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":true,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]}],"demarche_type_id":"mut","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"ordre":7},{"demarche_visibilite":"Publique","id":"3W0rdHS1VqDSIQjZ1mLD8b9L","slug":"m-cx-lenoncourt-1968-mut05","description":null,"etapes":[{"etape_type_id":"dpu","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["nacl"],"titulaireIds":["fr-442993283"],"amodiataireIds":null,"perimetre":null},"etape_statut_id":"fai","is_brouillon":false,"date":"2004-02-28","id":"isgwwZGJwv7UDuJvtxAaj3T4","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut05-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":false,"type":"text","value":"JORFTEXT000000434866"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"INDI0402498A"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"dex","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"acc","is_brouillon":false,"date":"2004-02-13","id":"Full4Vnptm6czWaJ4b6kZR6W","ordre":1,"note":{"valeur":"Arrêté du 13 février 2004 autorisant la mutation d’une concession de mines de sels de sodium","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut05-dex01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":true,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]}],"demarche_type_id":"mut","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"ordre":8},{"demarche_visibilite":"Publique","id":"fA9NJsMZ78XyG402LUdm2Szi","slug":"m-cx-lenoncourt-1968-pro01","description":"prolongation et extension de périmètre","etapes":[{"etape_type_id":"dpu","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":null,"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"fai","is_brouillon":false,"date":"2024-03-01","id":"a0af6a2e56cd046cd72c71cf","ordre":16,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-pro01-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":false,"type":"text","value":"JORFTEXT000049219226"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"ECOL2320431D"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"dex","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":null,"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"acc","is_brouillon":false,"date":"2024-02-29","id":"aa23dc021366330e04383eba","ordre":15,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-pro01-dex01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":true,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[{"id":"2024-02-29-dec-12df6369","type":"DESCRIPTION_OPTIONNELLE","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"dec","description":""},{"id":"2024-02-29-dec-4bb7fd91","type":"DESCRIPTION_OPTIONNELLE","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"dec","description":""}],"avis_documents":[]},{"etape_type_id":"adc","etape_statut_id":"fai","is_brouillon":false,"date":"2021-06-01","id":"ryW6mbg2cC906CimQRgdVhvd","ordre":7,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-pro01-adc01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"epu","etape_statut_id":"ter","is_brouillon":false,"date":"2021-04-20","id":"d1PRxUd0F9JHQSziUQ3skOem","ordre":6,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-pro01-epu01","sections_with_values":[{"id":"epu","elements":[{"id":"lien","nom":"Lien public externe","description":"","optionnel":true,"type":"url","value":null},{"id":"duree","nom":"Durée en jours de l'enquête publique","description":"","optionnel":false,"type":"number","value":43}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"mcr","etape_statut_id":"fav","is_brouillon":false,"date":"2021-01-27","id":"pHf3m1Hygp8kz8d7G0j2TKgZ","ordre":4,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-pro01-mcr01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"men","etape_statut_id":"fai","is_brouillon":false,"date":"2020-08-04","id":"mQnOvtSGpc1T83bSvOOorVOa","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-pro01-men01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"mfr", "demarche_id_en_concurrence": null, "demarches_consentement": [],"fondamentale":{"date_debut":null,"date_fin":null,"duree":300,"substances":["nacl"],"titulaireIds":["fr-442993283"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[6.255869021711159,48.675202067410254],[6.263459497281365,48.6611397799328],[6.274477936823362,48.661530617274785],[6.29531036181682,48.66798716858568],[6.3162302722649795,48.67616624512283],[6.31565519531486,48.68038643555574],[6.307660371971501,48.69025022534333],[6.302480013569365,48.68917854238857],[6.2963188041374485,48.68915103738882],[6.290983811108587,48.68777705995633],[6.285642745098623,48.68911271820202],[6.281739260684181,48.68909422269382],[6.275638319504659,48.68547207905551],[6.255869021711159,48.675202067410254]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[6.255869021711159,48.675202067410254]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.275638319504659,48.68547207905551]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.281739260684181,48.68909422269382]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.285642745098623,48.68911271820202]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.290983811108587,48.68777705995633]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2963188041374485,48.68915103738882]},"properties":{"nom":"F","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.302480013569365,48.68917854238857]},"properties":{"nom":"G","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.307660371971501,48.69025022534333]},"properties":{"nom":"H","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.31565519531486,48.68038643555574]},"properties":{"nom":"I","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3162302722649795,48.67616624512283]},"properties":{"nom":"J","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.29531036181682,48.66798716858568]},"properties":{"nom":"K","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.274477936823362,48.661530617274785]},"properties":{"nom":"L","description":"Nouveau sommet « d’extension » défini par NOVACARB"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.263459497281365,48.6611397799328]},"properties":{"nom":"M","description":"Nouveau sommet « d’extension » défini par NOVACARB"}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[939659,6846613],[941066,6847814],[941498,6848235],[941785,6848249],[942184,6848117],[942570,6848286],[943023,6848308],[943399,6848443],[944033,6847372],[944095,6846905],[942594,6845932],[941091,6845151],[940282,6845074],[939659,6846613]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[939659,6846613]},"properties":{"nom":"A"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[941066,6847814]},"properties":{"nom":"B"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[941498,6848235]},"properties":{"nom":"C"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[941785,6848249]},"properties":{"nom":"D"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[942184,6848117]},"properties":{"nom":"E"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[942570,6848286]},"properties":{"nom":"F"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[943023,6848308]},"properties":{"nom":"G"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[943399,6848443]},"properties":{"nom":"H"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[944033,6847372]},"properties":{"nom":"I"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[944095,6846905]},"properties":{"nom":"J"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[942594,6845932]},"properties":{"nom":"K"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[941091,6845151]},"properties":{"nom":"L","description":"Nouveau sommet « d’extension » défini par NOVACARB"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[940282,6845074]},"properties":{"nom":"M","description":"Nouveau sommet « d’extension » défini par NOVACARB"}}]},"geojson_origine_geo_systeme_id":"2154","geojson4326_forages":null,"geojson_origine_forages":null,"surface":9.05,"communes":[{"id":"54495","nom":"Saulxures-lès-Nancy"},{"id":"54311","nom":"Lenoncourt"},{"id":"54110","nom":"Cerville"},{"id":"54025","nom":"Art-sur-Meurthe"}],"secteurs_maritimes":[],"sdom_zones":[],"forets":[]}},"etape_statut_id":"fai","is_brouillon":false,"date":"2020-07-06","id":"mh70cpBA8jOZWCEDJKupM4Rs","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-pro01-mfr01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]}],"demarche_type_id":"pro","demarche_statut_id":"acc","demarche_date_debut":"2024-03-01","demarche_date_fin":"2049-03-01","ordre":11},{"demarche_visibilite":"Publique","id":"b7586ad241a658ae1eb42b08","slug":"m-cx-lenoncourt-1968-exp02","description":"","etapes":[{"etape_type_id":"dpu","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":null,"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_statut_id":"fai","is_brouillon":false,"date":"2024-03-01","id":"e48a19b86d090feadc67a893","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-exp02-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":false,"type":"text","value":"JORFTEXT000049219226"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"ECOL2320431D"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[]},{"etape_type_id":"dex","fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["nacl"],"titulaireIds":["fr-442993283"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[6.2559,48.6752],[6.2756,48.6855],[6.2817,48.6891],[6.2856,48.6891],[6.291,48.6878],[6.2963,48.6892],[6.3025,48.6892],[6.3076,48.689],[6.3157,48.6804],[6.3162,48.6762],[6.2953,48.668],[6.2794,48.6631],[6.2614,48.6649],[6.2559,48.6752]]]]}},"geojson4326_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2559,48.6752]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2756,48.6855]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2817,48.6891]},"properties":{"nom":"B1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2856,48.6891]},"properties":{"nom":"C1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.291,48.6878]},"properties":{"nom":"D1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2963,48.6892]},"properties":{"nom":"E1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3025,48.6892]},"properties":{"nom":"F1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3076,48.689]},"properties":{"nom":"G1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3157,48.6804]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3162,48.6762]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2953,48.668]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2794,48.6631]},"properties":{"nom":"Da","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2614,48.6649]},"properties":{"nom":"Db","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2559,48.6752]},"properties":{"nom":"E","description":null}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[6.2559,48.6752],[6.2756,48.6855],[6.2817,48.6891],[6.2856,48.6891],[6.291,48.6878],[6.2963,48.6892],[6.3025,48.6892],[6.3076,48.689],[6.3157,48.6804],[6.3162,48.6762],[6.2953,48.668],[6.2794,48.6631],[6.2614,48.6649],[6.2559,48.6752]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2559,48.6752]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2756,48.6855]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2817,48.6891]},"properties":{"nom":"B1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2856,48.6891]},"properties":{"nom":"C1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.291,48.6878]},"properties":{"nom":"D1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2963,48.6892]},"properties":{"nom":"E1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3025,48.6892]},"properties":{"nom":"F1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3076,48.689]},"properties":{"nom":"G1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3157,48.6804]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3162,48.6762]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2953,48.668]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2794,48.6631]},"properties":{"nom":"Da","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2614,48.6649]},"properties":{"nom":"Db","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2559,48.6752]},"properties":{"nom":"E","description":null}}]},"geojson_origine_geo_systeme_id":"4326","geojson4326_forages":null,"geojson_origine_forages":null,"surface":8.65,"communes":[{"id":"54495","nom":"Saulxures-lès-Nancy"},{"id":"54311","nom":"Lenoncourt"},{"id":"54110","nom":"Cerville"},{"id":"54025","nom":"Art-sur-Meurthe"}],"secteurs_maritimes":[],"sdom_zones":[],"forets":[]}},"etape_statut_id":"acc","is_brouillon":false,"date":"2024-02-29","id":"c15f4ceaa62a6298a2f8e117","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-exp02-dex01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"","optionnel":true,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[{"id":"2024-02-29-dec-d9f1e868","type":"DESCRIPTION_OPTIONNELLE","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"dec","description":""},{"id":"2024-02-29-dec-32312304","type":"DESCRIPTION_OPTIONNELLE","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"dec","description":""}],"avis_documents":[]}],"demarche_type_id":"exp","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"ordre":12}],"nb_activites_to_do":null}) + const lenoncourtData = titreGetValidator.parse({"id":"s7RvqvCAgKs4DxkQBYV93cVx","nom":"Lenoncourt","slug":"m-cx-lenoncourt-1968","titre_type_id":"cxm","titre_statut_id":"val","titre_visibilite":"Publique","titre_doublon":null,"references":[{"nom":"2013-0275-MI","referenceTypeId":"deb"},{"nom":"54TM0153","referenceTypeId":"rnt"}],"titre_last_modified_date":null,"demarches":[{"id":"ozYnUjy40eru81jUnXz5snv2","slug":"m-cx-lenoncourt-1968-oct01","description":null,"etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"1968-01-24","id":"SG2zAN9QaKBN1hZKqKEgQGpI","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-oct01-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[{"type":"DESCRIPTION_OPTIONNELLE","id":"1968-01-24-dec-89a94bb2","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"dec","description":"Décret du 13 janvier 1968 instituant la concession de mines de sels de sodium de Lenoncourt (Meurthe-et-Moselle) au profit de la société Les Soudières réunies - La Madeleine-Varangéville"}],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["nacl"],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"1968-01-13","id":"LM2Zk3PwAjrduc4EqmucOjeB","ordre":1,"note":{"valeur":"Décret du 13 janvier 1968 instituant la concession de mines de sels de sodium de Lenoncourt (Meurthe-et-Moselle) au profit de la société Les Soudières réunies - La Madeleine-Varangéville","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-oct01-dex01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dex"}],"demarche_type_id":"oct","demarche_statut_id":"acc","demarche_date_debut":"1968-01-24","demarche_date_fin":"2024-03-01","demarche_visibilite":"Publique","machine_id":null,"ordre":1},{"id":"wM0cpipWSef9lDAHDurJxxhk","slug":"m-cx-lenoncourt-1968-mut01","description":null,"etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"1970-11-19","id":"XScxzwDKFxmYtDnkJ7X7qZBi","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut01-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[{"type":"DESCRIPTION_OPTIONNELLE","id":"1970-11-19-dec-8a77b142","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"dec","description":"Décret du 16 novembre 1970 autorisant la mutation de propriété de cinq concessions de mines de sel gemme et de sources salées au profit de la société Produits chimiques Pechlney-Saint-Gobaln."}],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["selg","selh"],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"1970-11-16","id":"ejAqTpzBj82jgF0ShiwMRQmW","ordre":1,"note":{"valeur":"Décret du 16 novembre 1970 autorisant la mutation de propriété de cinq concessions de mines de sel gemme et de sources salées au profit de la société Produits chimiques Pechlney-Saint-Gobaln.","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut01-dex01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":["fr-606320471"],"amodiataireIds":null,"perimetre":null},"etape_type_id":"dex"}],"demarche_type_id":"mut","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"demarche_visibilite":"Publique","machine_id":null,"ordre":2},{"id":"1UC2b0ORsm2ezCh6whHzbOKR","slug":"m-cx-lenoncourt-1968-mut02","description":null,"etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"1975-11-27","id":"TjimKkEETzF0yGBG2m085on9","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut02-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":null},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[{"type":"DESCRIPTION_OPTIONNELLE","id":"1975-11-27-dec-b50a06f5","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"dec","description":"Décret du 24 novembre 1975 autorisant la mutation de cinq concessions de mines de sel gemme et de sources salées au profit de la Compagnie industrielle et minière"}],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["selg","selh"],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"1975-11-24","id":"aYO0zwBFBOZP7VN11JaJDhzI","ordre":1,"note":{"valeur":"Décret du 24 novembre 1975 autorisant la mutation de cinq concessions de mines de sel gemme et de sources salées au profit de la Compagnie industrielle et minière","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut02-dex01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":["fr-712025048"],"amodiataireIds":null,"perimetre":null},"etape_type_id":"dex"}],"demarche_type_id":"mut","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"demarche_visibilite":"Publique","machine_id":null,"ordre":3},{"id":"H5eANAZPKhY9eFQtCyLYjCvp","slug":"m-cx-lenoncourt-1968-exp01","description":null,"etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"1981-09-13","id":"C6UHWZDSFnLbwuaeksXG1SEj","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-exp01-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":"N"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":null}]}],"entreprises_documents":[],"etape_documents":[{"type":"DESCRIPTION_OPTIONNELLE","id":"1981-09-13-dec-8bf8fa4c","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"dec","description":"Décret du 9 septembre 1981 portant extension de superficie de la concession des mines de sels de sodium de Lenoncourt (Meurthe-et-Moselle) et modifiant les conditions auxquelles est soumise ladite concession"}],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["nacl"],"titulaireIds":["fr-712025048"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[6.275644095814427,48.6854960696669],[6.255874124806144,48.675237870291575],[6.295319143383101,48.66801114312286],[6.316241924966296,48.676189123934925],[6.315656943097024,48.680413137182065],[6.307671761547864,48.69027442550079],[6.302487495007789,48.68919858322589],[6.296317613859298,48.68917495187758],[6.290997693817669,48.68780534512822],[6.285653764289864,48.68913324659737],[6.281744418990354,48.68911774206666],[6.275644095814427,48.6854960696669]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[6.275644095814427,48.6854960696669]},"properties":{"nom":"A","description":"Point situé sur la ligne joignant les clochers de Saulxures-lès-Nancy et de Buissoncourt, à son intersection avec la limite des communes de Saulxures-lès-Nancy et de Lenoncourt, soit à environ 2040 mètres à l'Est-Sud-Est du clocher de Saulxures-lès-Nancy"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.281744418990354,48.68911774206666]},"properties":{"nom":"B1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.285653764289864,48.68913324659737]},"properties":{"nom":"C1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.290997693817669,48.68780534512822]},"properties":{"nom":"D1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.296317613859298,48.68917495187758]},"properties":{"nom":"E1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.302487495007789,48.68919858322589]},"properties":{"nom":"F1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.307671761547864,48.69027442550079]},"properties":{"nom":"G1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.315656943097024,48.680413137182065]},"properties":{"nom":"B","description":"Point situé sur la ligne joignant les clochers de Saulxures-lès-Nancy et de Buissoncourt, à son intersection avec la limite Ouest de la concession de Cercueil-Buissoncourt, soit à environ 2 150 mètres au Nord-Nord-Ouest du clocher de Buissoncourt"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.316241924966296,48.676189123934925]},"properties":{"nom":"C","description":"Borne commune aux concessions d'Art-sur-Meurthe et de Cercueil-Buissoncourt"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.295319143383101,48.66801114312286]},"properties":{"nom":"D","description":"Sommet A de la concession d'Art-sur-Meurthe:"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.255874124806144,48.675237870291575]},"properties":{"nom":"E","description":"Sommet M de la concession d'Art-sur•Meurthe:"}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[889907.42,1117010.26],[890334.9,1117435.93],[890622.24,1117452.72],[891022.89,1117325.88],[891406.04,1117498.53],[891859.53,1117525.03],[892234.39,1117664.59],[892879.34,1116600.52],[892947.15,1116133.73],[891456.2,1115144.46],[888513.03,1115795.21],[889907.42,1117010.26]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[889907.42,1117010.26]},"properties":{"nom":"A","description":"Point situé sur la ligne joignant les clochers de Saulxures-lès-Nancy et de Buissoncourt, à son intersection avec la limite des communes de Saulxures-lès-Nancy et de Lenoncourt, soit à environ 2040 mètres à l’Est-Sud-Est du clocher de Saulxures-lès-Nancy"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[890334.9,1117435.93]},"properties":{"nom":"B1"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[890622.24,1117452.72]},"properties":{"nom":"C1"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[891022.89,1117325.88]},"properties":{"nom":"D1"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[891406.04,1117498.53]},"properties":{"nom":"E1"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[891859.53,1117525.03]},"properties":{"nom":"F1"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[892234.39,1117664.59]},"properties":{"nom":"G1"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[892879.34,1116600.52]},"properties":{"nom":"B","description":"Point situé sur la ligne joignant les clochers de Saulxures-lès-Nancy et de Buissoncourt, à son intersection avec la limite Ouest de la concession de Cercueil-Buissoncourt, soit à environ 2 150 mètres au Nord-Nord-Ouest du clocher de Buissoncourt"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[892947.15,1116133.73]},"properties":{"nom":"C","description":"Borne commune aux concessions d’Art-sur-Meurthe et de Cercueil-Buissoncourt"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[891456.2,1115144.46]},"properties":{"nom":"D","description":"Sommet A de la concession d’Art-sur-Meurthe:"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[888513.03,1115795.21]},"properties":{"nom":"E","description":"Sommet M de la concession d’Art-sur•Meurthe:"}}]},"geojson_origine_geo_systeme_id":"27571","geojson4326_forages":null,"geojson_origine_forages":null,"surface":6.75,"communes":[{"id":"54025","nom":"Art-sur-Meurthe"},{"id":"54110","nom":"Cerville"},{"id":"54311","nom":"Lenoncourt"},{"id":"54495","nom":"Saulxures-lès-Nancy"}],"secteurs_maritimes":[],"sdom_zones":[],"forets":[]}},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"1981-09-09","id":"xHxKuYk5goClAaZr1hxGaCyr","ordre":1,"note":{"valeur":"Décret du 9 septembre 1981 portant extension de superficie de la concession des mines de sels de sodium de Lenoncourt (Meurthe-et-Moselle) et modifiant les conditions auxquelles est soumise ladite concession","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-exp01-dex01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dex"}],"demarche_type_id":"exp","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"demarche_visibilite":"Publique","machine_id":null,"ordre":4},{"id":"D9Mo17XmpzCAr4SLdVAKbPPS","slug":"m-cx-lenoncourt-1968-aom01","description":null,"etapes":[{"etape_statut_id":"ter","is_brouillon":false,"date":"2000-06-07","id":"U1ylgIqovJcLUMZwU7MVy9C8","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-aom01-epu01","sections_with_values":[{"id":"epu","elements":[{"id":"lien","nom":"Lien public externe","description":"","optionnel":true,"type":"url","value":null},{"id":"duree","nom":"Durée en jours de l'enquête publique","optionnel":false,"type":"number","value":30}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"epu"}],"demarche_type_id":"aom","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"demarche_visibilite":"Publique","machine_id":null,"ordre":5},{"id":"W9IX7VanFA5iYxYAGulcA0CY","slug":"m-cx-lenoncourt-1968-mut03","description":null,"etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"2000-10-06","id":"wuYTEAQ5UUAUZxiowQIthgkg","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut03-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":"JORFTEXT000000208330"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"ECOI0000456A"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["nacl"],"titulaireIds":["fr-442993283"],"amodiataireIds":null,"perimetre":null},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"2000-09-26","id":"f2iSnn7XPrOXDIrbmYFKUiz1","ordre":1,"note":{"valeur":"Arrêté du 26 septembre 2000 autorisant la mutation de concessions de mines","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut03-dex01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dex"}],"demarche_type_id":"mut","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"demarche_visibilite":"Publique","machine_id":null,"ordre":6},{"id":"md9yLbhZSOqdcOANAAyUPTur","slug":"m-cx-lenoncourt-1968-mut04","description":null,"etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"2003-01-08","id":"yuMPprDNtN6mZzdmlVTDd25I","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut04-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":"JORFTEXT000000228627"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"INDI0200856A"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["nacl"],"titulaireIds":["fr-642014526"],"amodiataireIds":null,"perimetre":null},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"2002-12-24","id":"jZRW7aZo5DmTABnQCe35wVrh","ordre":1,"note":{"valeur":"Arrêté du 24 décembre 2002 autorisant la mutation de concessions de mines","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut04-dex01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dex"}],"demarche_type_id":"mut","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"demarche_visibilite":"Publique","machine_id":null,"ordre":7},{"id":"3W0rdHS1VqDSIQjZ1mLD8b9L","slug":"m-cx-lenoncourt-1968-mut05","description":null,"etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"2004-02-28","id":"isgwwZGJwv7UDuJvtxAaj3T4","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut05-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":"JORFTEXT000000434866"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"INDI0402498A"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["nacl"],"titulaireIds":["fr-442993283"],"amodiataireIds":null,"perimetre":null},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"2004-02-13","id":"Full4Vnptm6czWaJ4b6kZR6W","ordre":1,"note":{"valeur":"Arrêté du 13 février 2004 autorisant la mutation d’une concession de mines de sels de sodium","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-mut05-dex01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":[],"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dex"}],"demarche_type_id":"mut","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"demarche_visibilite":"Publique","machine_id":null,"ordre":8},{"id":"owienIKBTyuI4fqnMnnxQcr7","slug":"m-cx-lenoncourt-1968-aom02","description":null,"etapes":[{"etape_statut_id":"ter","is_brouillon":false,"date":"2012-05-15","id":"AwMURNmnalaI4nbg9xjGV3Pd","ordre":3,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-aom02-epu01","sections_with_values":[{"id":"epu","elements":[{"id":"lien","nom":"Lien public externe","description":"","optionnel":true,"type":"url","value":null},{"id":"duree","nom":"Durée en jours de l'enquête publique","optionnel":false,"type":"number","value":31}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"epu"},{"etape_statut_id":"fav","is_brouillon":false,"date":"2012-02-29","id":"X4ls8xEATv3kZlpv5DvmSVMD","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-aom02-mcr01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"mcr"}],"demarche_type_id":"aom","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"demarche_visibilite":"Publique","machine_id":null,"ordre":9},{"id":"FadRy9eULBgbbAIZN5SAb8Ko","slug":"m-cx-lenoncourt-1968-aom03","description":null,"etapes":[{"etape_statut_id":"ter","is_brouillon":false,"date":"2019-05-31","id":"pqAQb6FvFPod5sINYb8dFoGI","ordre":3,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-aom03-epu01","sections_with_values":[{"id":"epu","elements":[{"id":"lien","nom":"Lien public externe","description":"","optionnel":true,"type":"url","value":null},{"id":"duree","nom":"Durée en jours de l'enquête publique","optionnel":false,"type":"number","value":42}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"epu"},{"etape_statut_id":"fav","is_brouillon":false,"date":"2019-03-11","id":"BnLPo5p3gS2D4yKWoFCqR3vb","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-aom03-mcr01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"mcr"}],"demarche_type_id":"aom","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"demarche_visibilite":"Publique","machine_id":null,"ordre":10},{"id":"fA9NJsMZ78XyG402LUdm2Szi","slug":"m-cx-lenoncourt-1968-pro01","description":"prolongation et extension de périmètre","etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"2024-03-01","id":"a0af6a2e56cd046cd72c71cf","ordre":14,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-pro01-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":"JORFTEXT000049219226"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"ECOL2320431D"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":null,"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"2024-02-29","id":"aa23dc021366330e04383eba","ordre":13,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-pro01-dex01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[{"type":"DESCRIPTION_OPTIONNELLE","id":"2024-02-29-dec-12df6369","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"dec","description":""},{"type":"DESCRIPTION_OPTIONNELLE","id":"2024-02-29-dec-4bb7fd91","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"dec","description":""}],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":null,"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dex"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2021-06-01","id":"ryW6mbg2cC906CimQRgdVhvd","ordre":7,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-pro01-adc01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"adc"},{"etape_statut_id":"ter","is_brouillon":false,"date":"2021-04-20","id":"d1PRxUd0F9JHQSziUQ3skOem","ordre":6,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-pro01-epu01","sections_with_values":[{"id":"epu","elements":[{"id":"lien","nom":"Lien public externe","description":"","optionnel":true,"type":"url","value":null},{"id":"duree","nom":"Durée en jours de l'enquête publique","optionnel":false,"type":"number","value":43}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"epu"},{"etape_statut_id":"fav","is_brouillon":false,"date":"2021-01-27","id":"pHf3m1Hygp8kz8d7G0j2TKgZ","ordre":4,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-pro01-mcr01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"mcr"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2020-08-04","id":"mQnOvtSGpc1T83bSvOOorVOa","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-pro01-men01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"etape_type_id":"men"},{"etape_statut_id":"fai","is_brouillon":false,"date":"2020-07-06","id":"mh70cpBA8jOZWCEDJKupM4Rs","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-pro01-mfr01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"demarches_consentement":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":300,"substances":["nacl"],"titulaireIds":["fr-442993283"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[6.255869021711159,48.675202067410254],[6.263459497281365,48.6611397799328],[6.274477936823362,48.661530617274785],[6.29531036181682,48.66798716858568],[6.3162302722649795,48.67616624512283],[6.31565519531486,48.68038643555574],[6.307660371971501,48.69025022534333],[6.302480013569365,48.68917854238857],[6.2963188041374485,48.68915103738882],[6.290983811108587,48.68777705995633],[6.285642745098623,48.68911271820202],[6.281739260684181,48.68909422269382],[6.275638319504659,48.68547207905551],[6.255869021711159,48.675202067410254]]]]}},"geojson4326_points":{"type":"FeatureCollection","properties":{},"features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[6.255869021711159,48.675202067410254]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.275638319504659,48.68547207905551]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.281739260684181,48.68909422269382]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.285642745098623,48.68911271820202]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.290983811108587,48.68777705995633]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2963188041374485,48.68915103738882]},"properties":{"nom":"F","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.302480013569365,48.68917854238857]},"properties":{"nom":"G","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.307660371971501,48.69025022534333]},"properties":{"nom":"H","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.31565519531486,48.68038643555574]},"properties":{"nom":"I","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3162302722649795,48.67616624512283]},"properties":{"nom":"J","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.29531036181682,48.66798716858568]},"properties":{"nom":"K","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.274477936823362,48.661530617274785]},"properties":{"nom":"L","description":"Nouveau sommet « d’extension » défini par NOVACARB"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.263459497281365,48.6611397799328]},"properties":{"nom":"M","description":"Nouveau sommet « d’extension » défini par NOVACARB"}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[939659,6846613],[941066,6847814],[941498,6848235],[941785,6848249],[942184,6848117],[942570,6848286],[943023,6848308],[943399,6848443],[944033,6847372],[944095,6846905],[942594,6845932],[941091,6845151],[940282,6845074],[939659,6846613]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[939659,6846613]},"properties":{"nom":"A"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[941066,6847814]},"properties":{"nom":"B"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[941498,6848235]},"properties":{"nom":"C"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[941785,6848249]},"properties":{"nom":"D"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[942184,6848117]},"properties":{"nom":"E"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[942570,6848286]},"properties":{"nom":"F"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[943023,6848308]},"properties":{"nom":"G"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[943399,6848443]},"properties":{"nom":"H"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[944033,6847372]},"properties":{"nom":"I"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[944095,6846905]},"properties":{"nom":"J"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[942594,6845932]},"properties":{"nom":"K"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[941091,6845151]},"properties":{"nom":"L","description":"Nouveau sommet « d’extension » défini par NOVACARB"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[940282,6845074]},"properties":{"nom":"M","description":"Nouveau sommet « d’extension » défini par NOVACARB"}}]},"geojson_origine_geo_systeme_id":"2154","geojson4326_forages":null,"geojson_origine_forages":null,"surface":9.05,"communes":[{"id":"54025","nom":"Art-sur-Meurthe"},{"id":"54110","nom":"Cerville"},{"id":"54311","nom":"Lenoncourt"},{"id":"54495","nom":"Saulxures-lès-Nancy"}],"secteurs_maritimes":[],"sdom_zones":[],"forets":[]}},"etape_type_id":"mfr","demarche_id_en_concurrence":null}],"demarche_type_id":"pro","demarche_statut_id":"acc","demarche_date_debut":"2024-03-01","demarche_date_fin":"2049-03-01","demarche_visibilite":"Publique","machine_id":null,"ordre":11},{"id":"b7586ad241a658ae1eb42b08","slug":"m-cx-lenoncourt-1968-exp02","description":"","etapes":[{"etape_statut_id":"fai","is_brouillon":false,"date":"2024-03-01","id":"e48a19b86d090feadc67a893","ordre":2,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-exp02-dpu01","sections_with_values":[{"id":"publication","nom":"Références Légifrance","elements":[{"id":"jorf","nom":"Numéro JORF","description":"Le numéro de JORF à rentrer est la dernière partie de l'URL du JORF. <br /> Par exemple dans l'URL https://www.legifrance.gouv.fr/jorf/id/JORFTEXTXXXXXXXXXX le numéro est <b>JORFTEXTXXXXXXXXXX</b>","optionnel":false,"type":"text","value":"JORFTEXT000049219226"},{"id":"nor","nom":"Numéro NOR","description":"","optionnel":true,"type":"text","value":"ECOL2320431D"}]}],"entreprises_documents":[],"etape_documents":[],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":null,"titulaireIds":null,"amodiataireIds":null,"perimetre":null},"etape_type_id":"dpu"},{"etape_statut_id":"acc","is_brouillon":false,"date":"2024-02-29","id":"c15f4ceaa62a6298a2f8e117","ordre":1,"note":{"valeur":"","is_avertissement":false},"slug":"m-cx-lenoncourt-1968-exp02-dex01","sections_with_values":[],"entreprises_documents":[],"etape_documents":[{"type":"DESCRIPTION_OPTIONNELLE","id":"2024-02-29-dec-d9f1e868","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"dec","description":""},{"type":"DESCRIPTION_OPTIONNELLE","id":"2024-02-29-dec-32312304","public_lecture":true,"entreprises_lecture":true,"etape_document_type_id":"dec","description":""}],"avis_documents":[],"fondamentale":{"date_debut":null,"date_fin":null,"duree":null,"substances":["nacl"],"titulaireIds":["fr-442993283"],"amodiataireIds":null,"perimetre":{"geojson4326_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[6.2559,48.6752],[6.2756,48.6855],[6.2817,48.6891],[6.2856,48.6891],[6.291,48.6878],[6.2963,48.6892],[6.3025,48.6892],[6.3076,48.689],[6.3157,48.6804],[6.3162,48.6762],[6.2953,48.668],[6.2794,48.6631],[6.2614,48.6649],[6.2559,48.6752]]]]}},"geojson4326_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2559,48.6752]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2756,48.6855]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2817,48.6891]},"properties":{"nom":"B1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2856,48.6891]},"properties":{"nom":"C1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.291,48.6878]},"properties":{"nom":"D1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2963,48.6892]},"properties":{"nom":"E1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3025,48.6892]},"properties":{"nom":"F1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3076,48.689]},"properties":{"nom":"G1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3157,48.6804]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3162,48.6762]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2953,48.668]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2794,48.6631]},"properties":{"nom":"Da","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2614,48.6649]},"properties":{"nom":"Db","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2559,48.6752]},"properties":{"nom":"E","description":null}}]},"geojson_origine_perimetre":{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[6.2559,48.6752],[6.2756,48.6855],[6.2817,48.6891],[6.2856,48.6891],[6.291,48.6878],[6.2963,48.6892],[6.3025,48.6892],[6.3076,48.689],[6.3157,48.6804],[6.3162,48.6762],[6.2953,48.668],[6.2794,48.6631],[6.2614,48.6649],[6.2559,48.6752]]]]}},"geojson_origine_points":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2559,48.6752]},"properties":{"nom":"E","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2756,48.6855]},"properties":{"nom":"A","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2817,48.6891]},"properties":{"nom":"B1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2856,48.6891]},"properties":{"nom":"C1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.291,48.6878]},"properties":{"nom":"D1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2963,48.6892]},"properties":{"nom":"E1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3025,48.6892]},"properties":{"nom":"F1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3076,48.689]},"properties":{"nom":"G1","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3157,48.6804]},"properties":{"nom":"B","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.3162,48.6762]},"properties":{"nom":"C","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2953,48.668]},"properties":{"nom":"D","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2794,48.6631]},"properties":{"nom":"Da","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2614,48.6649]},"properties":{"nom":"Db","description":null}},{"type":"Feature","geometry":{"type":"Point","coordinates":[6.2559,48.6752]},"properties":{"nom":"E","description":null}}]},"geojson_origine_geo_systeme_id":"4326","geojson4326_forages":null,"geojson_origine_forages":null,"surface":8.65,"communes":[{"id":"54025","nom":"Art-sur-Meurthe"},{"id":"54110","nom":"Cerville"},{"id":"54311","nom":"Lenoncourt"},{"id":"54495","nom":"Saulxures-lès-Nancy"}],"secteurs_maritimes":[],"sdom_zones":[],"forets":[]}},"etape_type_id":"dex"}],"demarche_type_id":"exp","demarche_statut_id":"acc","demarche_date_debut":null,"demarche_date_fin":null,"demarche_visibilite":"Publique","machine_id":null,"ordre":12}],"nb_activites_to_do":null}) return Promise.resolve(lenoncourtData) }, @@ -802,6 +802,7 @@ export const TitreAvecUnOctroiEnConstructionEtUnTravaux: StoryFn = () => ( { ...titre.demarches[0], demarche_date_debut: null, + machine_id: 'ProcedureSpecifique', }, { id: demarcheIdValidator.parse('idtravaux'), @@ -814,6 +815,7 @@ export const TitreAvecUnOctroiEnConstructionEtUnTravaux: StoryFn = () => ( demarche_date_debut: null, demarche_date_fin: null, demarche_visibilite: 'Confidentielle', + machine_id: null, }, ], }) diff --git a/packages/ui/src/components/titre.stories_snapshots_BasseManaMod.html b/packages/ui/src/components/titre.stories_snapshots_BasseManaMod.html index 2ac6e2f49..30d8cd539 100644 --- a/packages/ui/src/components/titre.stories_snapshots_BasseManaMod.html +++ b/packages/ui/src/components/titre.stories_snapshots_BasseManaMod.html @@ -17,6 +17,8 @@ </div> <div class="fr-mt-2w">Références<div style="font-weight: 500;">DEAL : 22/2018</div> <div style="font-weight: 500;">DEB : 2016-0010-MI</div> + <div style="font-weight: 500;">DEAL : R16-08</div> + <div style="font-weight: 500;">DEAL : R23-02</div> </div> <div class="fr-grid-row fr-grid-row--middle fr-mt-4w"> <!----> @@ -39,8 +41,8 @@ <h2>Phases</h2> <ul> <li class="_hidden_b2e482"><a href="/mocked-href" title="Voir la phase Octroi du 11-09-2018" aria-label="Voir la phase Octroi du 11-09-2018" tab-index="-1">Voir la phase Octroi du 11-09-2018</a></li> + <li class="_hidden_b2e482"><a href="/mocked-href" title="Voir l'événement Prolongation 2 du 2024-05-17 lié à la phase Octroi" aria-label="Voir l'événement Prolongation 2 du 2024-05-17 lié à la phase Octroi" tab-index="-1">Voir l'événement Prolongation 2 du 17-05-2024 lié à la phase Octroi</a></li> <li class="_hidden_b2e482"><a href="/mocked-href" title="Voir la phase Prolongation 1 du 11-09-2021" aria-label="Voir la phase Prolongation 1 du 11-09-2021" aria-current="page" tab-index="-1">Voir la phase Prolongation 1 du 11-09-2021</a></li> - <li class="_hidden_b2e482"><a href="/mocked-href" title="Voir l'événement Prolongation 2 du 2023-10-30 lié à la phase Prolongation 1" aria-label="Voir l'événement Prolongation 2 du 2023-10-30 lié à la phase Prolongation 1" tab-index="-1">Voir l'événement Prolongation 2 du 30-10-2023 lié à la phase Prolongation 1</a></li> </ul> <div style="overflow-x: auto;" aria-hidden="true" tabindex="-1"> <div class="fr-mx-4w"> @@ -56,11 +58,11 @@ </div> <div style="display: flex; width: 100%;"> <div style="display: flex; gap: 5px; position: relative; height: 20px; flex: 1;"> - <div class="_phasesContainer_b2e482" style="flex: 1;"><a tabindex="-1" href="/mocked-href" title="Octroi" class="_phase_b2e482" aria-label="Octroi" style="min-width: 200px;"></a></div> - <div style="border: 2px solid black;"></div> - <div class="_phasesContainer_b2e482" style="flex: 1;"><a tabindex="-1" href="/mocked-href" title="Prolongation 1" class="_phase_b2e482" aria-label="Prolongation 1" aria-current="page" style="min-width: 200px;"><a tabindex="-1" href="/mocked-href" title="Prolongation 2" class="_event_b2e482" aria-label="Prolongation 2" aria-describedby="timeline-event-m-pr-basse-mana-2018-pr201"> + <div class="_phasesContainer_b2e482" style="flex: 1;"><a tabindex="-1" href="/mocked-href" title="Octroi" class="_phase_b2e482" aria-label="Octroi" style="min-width: 200px;"><a tabindex="-1" href="/mocked-href" title="Prolongation 2" class="_event_b2e482" aria-label="Prolongation 2" aria-describedby="timeline-event-m-pr-basse-mana-2018-pr201"> <!----> </a></a></div> + <div style="border: 2px solid black;"></div> + <div class="_phasesContainer_b2e482" style="flex: 1;"><a tabindex="-1" href="/mocked-href" title="Prolongation 1" class="_phase_b2e482" aria-label="Prolongation 1" aria-current="page" style="min-width: 200px;"></a></div> <!----> </div> <div style="border-width: 0px 4px 4px 0px; padding: 8px; display: inline-block; transform: rotate(-45deg); margin-left: -20px;"></div> @@ -497,8 +499,8 @@ <div> <div class="fr-text--sm fr-mb-0">Durée en jours de la consultation du public</div> <div class="fr-text--md fr-mb-0" style="font-weight: 500;"> - <p>15 - <!----><span class="fr-info-text fr-mt-0">Du 27-03-2023 au 10-04-2023 (inclus)</span> + <p>18 + <!----><span class="fr-info-text fr-mt-0">Du 27-03-2023 au 13-04-2023 (inclus)</span> </p> </div> </div> diff --git a/packages/ui/src/components/titre.stories_snapshots_BonEspoirOctroi.html b/packages/ui/src/components/titre.stories_snapshots_BonEspoirOctroi.html index 910a4e7c1..501993d3b 100644 --- a/packages/ui/src/components/titre.stories_snapshots_BonEspoirOctroi.html +++ b/packages/ui/src/components/titre.stories_snapshots_BonEspoirOctroi.html @@ -120,7 +120,14 @@ <div class="fr-text--sm fr-mb-0">Substances</div> <div class="fr-text--md fr-mb-0" style="font-weight: 500;">Or, Substances connexes</div> </div> - <!----> + <div> + <div class="fr-text--sm fr-mb-0">Titulaire</div> + <div class="fr-text--md fr-mb-0" style="font-weight: 500;"> + <ul class="fr-m-0 fr-p-0" style="list-style: none;"> + <li><a href="/mocked-href" title="ARMINA RESSOURCES MINIERES SARL" class="fr-link" aria-label="ARMINA RESSOURCES MINIERES SARL">ARMINA RESSOURCES MINIERES SARL</a></li> + </ul> + </div> + </div> <!----> <div> <div class="fr-text--sm fr-mb-0">Administrations</div> @@ -359,7 +366,7 @@ </div> </div> <div style="display: flex;"> - <div class="fr-text--md">Surface : 465.5 Km²</div><a class="fr-btn fr-btn--secondary fr-btn--icon-right fr-icon-download-line" title="Télécharge les points au format csv" href="data:text/csv;charset=utf-8,nom;description;longitude;latitude;x_deg;y_deg%0A1;;-53.9579321010744;5.07776938770113;-53%C2%B057,476';5%C2%B04,666'%0A2;;-53.7596128864516;5.07864912381548;-53%C2%B045,577';5%C2%B04,719'%0A3;;-53.759383911755;5.02460196044417;-53%C2%B045,563';5%C2%B01,476'%0A4;;-53.5702069576163;5.02537608911083;-53%C2%B034,212';5%C2%B01,523'%0A5;;-53.5698730075868;4.93952315477954;-53%C2%B034,192';4%C2%B056,371'%0A6;;-53.7769878916108;4.93868722476635;-53%C2%B046,619';4%C2%B056,321'%0A7;;-53.7770631139658;4.95670276466037;-53%C2%B046,624';4%C2%B057,402'%0A8;;-53.8672265271601;4.95631734759459;-53%C2%B052,034';4%C2%B057,379'%0A9;;-53.8673626701318;4.98775355007457;-53%C2%B052,042';4%C2%B059,265'%0A10;;-53.9575232150351;4.98735333700249;-53%C2%B057,451';4%C2%B059,241'" download="points-m-pr-bon-espoir-2001.csv" style="margin-left: auto;">.csv</a> + <div class="fr-text--md">Surface : 464.71 Km²</div><a class="fr-btn fr-btn--secondary fr-btn--icon-right fr-icon-download-line" title="Télécharge les points au format csv" href="data:text/csv;charset=utf-8,nom;description;longitude;latitude;x_deg;y_deg%0A1;;-53.9579321010744;5.07776938770113;-53%C2%B057,476';5%C2%B04,666'%0A2;;-53.7596128864516;5.07864912381548;-53%C2%B045,577';5%C2%B04,719'%0A3;;-53.759383911755;5.02460196044417;-53%C2%B045,563';5%C2%B01,476'%0A4;;-53.5702069576163;5.02537608911083;-53%C2%B034,212';5%C2%B01,523'%0A5;;-53.5698730075868;4.93952315477954;-53%C2%B034,192';4%C2%B056,371'%0A6;;-53.7769878916108;4.93868722476635;-53%C2%B046,619';4%C2%B056,321'%0A7;;-53.7770631139658;4.95670276466037;-53%C2%B046,624';4%C2%B057,402'%0A8;;-53.8672265271601;4.95631734759459;-53%C2%B052,034';4%C2%B057,379'%0A9;;-53.8673626701318;4.98775355007457;-53%C2%B052,042';4%C2%B059,265'%0A10;;-53.9575232150351;4.98735333700249;-53%C2%B057,451';4%C2%B059,241'" download="points-m-pr-bon-espoir-2001.csv" style="margin-left: auto;">.csv</a> </div> </div> <!----> @@ -405,6 +412,62 @@ <div class="fr-text--sm fr-mb-0">Date de début</div> <div class="fr-text--md fr-mb-0" style="font-weight: 500;">01-11-2001</div> </div> + <!----> + <!----> + <!----> + <!----> + <!----> + <!----> + <div> + <div class="fr-text--sm fr-mb-0">Numéro JORF</div> + <div class="fr-text--md fr-mb-0" style="font-weight: 500;"> + <p><a target="_blank" rel="noopener noreferrer" href="https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000000774145" title="Numéro JORF Légifrance - Lien externe">JORFTEXT000000774145</a></p> + </div> + </div> + <div> + <div class="fr-text--sm fr-mb-0">Numéro NOR</div> + <div class="fr-text--md fr-mb-0" style="font-weight: 500;"> + <p>ECOI0100462D + <!----> + <!----> + </p> + </div> + </div> + <!----> + </div> + <!----> + <!----> + <!----> + <!----> + <!----> + </div> + </div> + <div class="fr-pb-2w"> + <div class="fr-pb-2w fr-pl-2w fr-pr-2w fr-tile--shadow"> + <div class="_sticky_964a6e fr-pt-1w"> + <div style="display: flex; justify-content: space-between; align-items: center;"> + <div style="display: flex;"> + <h4 class="fr-text--lg fr-mb-0" style="color: var(--text-title-blue-france); font-weight: 500;">Décision de l'autorité administrative</h4> + <!----> + </div> + <div style="display: flex; gap: 0.25rem;"> + <!----> + <!----> + <!----> + </div> + </div> + <p style="z-index: unset; margin-bottom: 0px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;" class="fr-badge fr-badge--md fr-badge--green-bourgeon" title="accepté" aria-label="accepté">accepté</p> + <div style="display: flex; justify-content: space-between; align-items: center;"> + <div class="fr-mt-1w"><span class="fr-icon-calendar-line" style="color: var(--text-title-blue-france);" aria-hidden="true"></span> 24-10-2001</div> + <div> + <p style="z-index: unset; margin-bottom: 0px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;" class="fr-badge fr-badge--md fr-badge--green-bourgeon" title="Étape publique" aria-label="Étape publique">Étape publique</p> + </div> + </div> + </div> + <!----> + <div class="fr-mb-3w fr-mt-3w" style="height: 1px; width: 100%; background-color: var(--grey-900-175);"></div> + <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); align-content: flex-start; column-gap: 16px; row-gap: 8px;"> + <!----> <div> <div class="fr-text--sm fr-mb-0">Durée</div> <div class="fr-text--md fr-mb-0" style="font-weight: 500;"><span><span>5 ans</span> @@ -417,11 +480,18 @@ <div class="fr-text--sm fr-mb-0">Substances</div> <div class="fr-text--md fr-mb-0" style="font-weight: 500;">Or, Substances connexes</div> </div> - <!----> + <div> + <div class="fr-text--sm fr-mb-0">Titulaire</div> + <div class="fr-text--md fr-mb-0" style="font-weight: 500;"> + <ul class="fr-m-0 fr-p-0" style="list-style: none;"> + <li><a href="/mocked-href" title="ARMINA RESSOURCES MINIERES SARL" class="fr-link" aria-label="ARMINA RESSOURCES MINIERES SARL">ARMINA RESSOURCES MINIERES SARL</a></li> + </ul> + </div> + </div> <!----> <div> <div class="fr-text--sm fr-mb-0">Surface</div> - <div class="fr-text--md fr-mb-0" style="font-weight: 500;">465,5 km² environ</div> + <div class="fr-text--md fr-mb-0" style="font-weight: 500;">464,71 km² environ</div> </div> <div> <div class="fr-text--sm fr-mb-0">Engagement</div> @@ -441,33 +511,21 @@ </p> </div> </div> - <div> - <div class="fr-text--sm fr-mb-0">Numéro JORF</div> - <div class="fr-text--md fr-mb-0" style="font-weight: 500;"> - <p><a target="_blank" rel="noopener noreferrer" href="https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000000774145" title="Numéro JORF Légifrance - Lien externe">JORFTEXT000000774145</a></p> - </div> - </div> - <div> - <div class="fr-text--sm fr-mb-0">Numéro NOR</div> - <div class="fr-text--md fr-mb-0" style="font-weight: 500;"> - <p>ECOI0100462D - <!----> - <!----> - </p> - </div> + <div style="grid-column: 1 / -1; white-space: pre-line;"> + <div class="fr-text--sm fr-mb-0">Notes</div> + <div class="fr-text--md fr-mb-0" style="font-weight: 500;">Décret du 24 octobre 2001 accordant un permis de recherches A en Guyane</div> </div> - <!----> </div> <div class="fr-pt-2w"> <div class="fr-tabs" style="--tabs-height: 0px;"> <ul class="fr-tabs__list" role="tablist" aria-label="Affichage des titres en vue carte ou tableau"> - <li role="presentation"><button id="tabpanel-carte-CRVhvEIQAc319vUd8BfZoH5W" class="fr-tabs__tab fr-icon-earth-fill fr-tabs__tab--icon-left" tabindex="-1" role="tab" aria-label="Carte" aria-selected="false" aria-controls="tabpanel-carte-CRVhvEIQAc319vUd8BfZoH5W-panel">Carte</button></li> - <li role="presentation"><button id="tabpanel-points-CRVhvEIQAc319vUd8BfZoH5W" class="fr-tabs__tab fr-icon-list-unordered fr-tabs__tab--icon-left" tabindex="0" role="tab" aria-label="Tableau" aria-selected="true" aria-controls="tabpanel-points-CRVhvEIQAc319vUd8BfZoH5W-panel">Tableau</button></li> + <li role="presentation"><button id="tabpanel-carte-Ce4K8goEZzjqXRJLL051jcpD" class="fr-tabs__tab fr-icon-earth-fill fr-tabs__tab--icon-left" tabindex="-1" role="tab" aria-label="Carte" aria-selected="false" aria-controls="tabpanel-carte-Ce4K8goEZzjqXRJLL051jcpD-panel">Carte</button></li> + <li role="presentation"><button id="tabpanel-points-Ce4K8goEZzjqXRJLL051jcpD" class="fr-tabs__tab fr-icon-list-unordered fr-tabs__tab--icon-left" tabindex="0" role="tab" aria-label="Tableau" aria-selected="true" aria-controls="tabpanel-points-Ce4K8goEZzjqXRJLL051jcpD-panel">Tableau</button></li> </ul> - <div id="tabpanel-carte-CRVhvEIQAc319vUd8BfZoH5W-panel" class="fr-tabs__panel fr-tabs__panel--direction-start" role="tabpanel" aria-labelledby="tabpanel-carte-CRVhvEIQAc319vUd8BfZoH5W" tabindex="0"> + <div id="tabpanel-carte-Ce4K8goEZzjqXRJLL051jcpD-panel" class="fr-tabs__panel fr-tabs__panel--direction-start" role="tabpanel" aria-labelledby="tabpanel-carte-Ce4K8goEZzjqXRJLL051jcpD" tabindex="0"> <!----> </div> - <div id="tabpanel-points-CRVhvEIQAc319vUd8BfZoH5W-panel" class="fr-tabs__panel fr-tabs__panel--selected" role="tabpanel" aria-labelledby="tabpanel-points-CRVhvEIQAc319vUd8BfZoH5W" tabindex="0"> + <div id="tabpanel-points-Ce4K8goEZzjqXRJLL051jcpD-panel" class="fr-tabs__panel fr-tabs__panel--selected" role="tabpanel" aria-labelledby="tabpanel-points-Ce4K8goEZzjqXRJLL051jcpD" tabindex="0"> <div style="display: flex; flex-direction: column;"> <div class="fr-select-group"><label class="fr-label" for="4326">Système géographique</label> <div id="4326_wrapper" class="_typeahead_8eddf1"> @@ -655,7 +713,7 @@ </div> </div> <div style="display: flex;"> - <div class="fr-text--md">Surface : 465.5 Km²</div><a class="fr-btn fr-btn--secondary fr-btn--icon-right fr-icon-download-line" title="Télécharge les points au format csv" href="data:text/csv;charset=utf-8,nom;description;longitude;latitude;x_deg;y_deg%0A1;;-53.9579321010744;5.07776938770113;-53%C2%B057,476';5%C2%B04,666'%0A2;;-53.7596128864516;5.07864912381548;-53%C2%B045,577';5%C2%B04,719'%0A3;;-53.759383911755;5.02460196044417;-53%C2%B045,563';5%C2%B01,476'%0A4;;-53.5702069576163;5.02537608911083;-53%C2%B034,212';5%C2%B01,523'%0A5;;-53.5698730075868;4.93952315477954;-53%C2%B034,192';4%C2%B056,371'%0A6;;-53.7769878916108;4.93868722476635;-53%C2%B046,619';4%C2%B056,321'%0A7;;-53.7770631139658;4.95670276466037;-53%C2%B046,624';4%C2%B057,402'%0A8;;-53.8672265271601;4.95631734759459;-53%C2%B052,034';4%C2%B057,379'%0A9;;-53.8673626701318;4.98775355007457;-53%C2%B052,042';4%C2%B059,265'%0A10;;-53.9575232150351;4.98735333700249;-53%C2%B057,451';4%C2%B059,241'" download="points-m-pr-bon-espoir-2001.csv" style="margin-left: auto;">.csv</a> + <div class="fr-text--md">Surface : 464.71 Km²</div><a class="fr-btn fr-btn--secondary fr-btn--icon-right fr-icon-download-line" title="Télécharge les points au format csv" href="data:text/csv;charset=utf-8,nom;description;longitude;latitude;x_deg;y_deg%0A1;;-53.9579321010744;5.07776938770113;-53%C2%B057,476';5%C2%B04,666'%0A2;;-53.7596128864516;5.07864912381548;-53%C2%B045,577';5%C2%B04,719'%0A3;;-53.759383911755;5.02460196044417;-53%C2%B045,563';5%C2%B01,476'%0A4;;-53.5702069576163;5.02537608911083;-53%C2%B034,212';5%C2%B01,523'%0A5;;-53.5698730075868;4.93952315477954;-53%C2%B034,192';4%C2%B056,371'%0A6;;-53.7769878916108;4.93868722476635;-53%C2%B046,619';4%C2%B056,321'%0A7;;-53.7770631139658;4.95670276466037;-53%C2%B046,624';4%C2%B057,402'%0A8;;-53.8672265271601;4.95631734759459;-53%C2%B052,034';4%C2%B057,379'%0A9;;-53.8673626701318;4.98775355007457;-53%C2%B052,042';4%C2%B059,265'%0A10;;-53.9575232150351;4.98735333700249;-53%C2%B057,451';4%C2%B059,241'" download="points-m-pr-bon-espoir-2001.csv" style="margin-left: auto;">.csv</a> </div> </div> <!----> @@ -669,50 +727,6 @@ <!----> </div> </div> - <div class="fr-pb-2w"> - <div class="fr-pb-2w fr-pl-2w fr-pr-2w fr-tile--shadow"> - <div class="_sticky_964a6e fr-pt-1w"> - <div style="display: flex; justify-content: space-between; align-items: center;"> - <div style="display: flex;"> - <h4 class="fr-text--lg fr-mb-0" style="color: var(--text-title-blue-france); font-weight: 500;">Décision de l'autorité administrative</h4> - <!----> - </div> - <div style="display: flex; gap: 0.25rem;"> - <!----> - <!----> - <!----> - </div> - </div> - <p style="z-index: unset; margin-bottom: 0px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;" class="fr-badge fr-badge--md fr-badge--green-bourgeon" title="accepté" aria-label="accepté">accepté</p> - <div style="display: flex; justify-content: space-between; align-items: center;"> - <div class="fr-mt-1w"><span class="fr-icon-calendar-line" style="color: var(--text-title-blue-france);" aria-hidden="true"></span> 24-10-2001</div> - <div> - <p style="z-index: unset; margin-bottom: 0px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;" class="fr-badge fr-badge--md fr-badge--green-bourgeon" title="Étape publique" aria-label="Étape publique">Étape publique</p> - </div> - </div> - </div> - <!----> - <div class="fr-mb-3w fr-mt-3w" style="height: 1px; width: 100%; background-color: var(--grey-900-175);"></div> - <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); align-content: flex-start; column-gap: 16px; row-gap: 8px;"> - <!----> - <!----> - <!----> - <!----> - <!----> - <!----> - <!----> - <div style="grid-column: 1 / -1; white-space: pre-line;"> - <div class="fr-text--sm fr-mb-0">Notes</div> - <div class="fr-text--md fr-mb-0" style="font-weight: 500;">Décret du 24 octobre 2001 accordant un permis de recherches A en Guyane</div> - </div> - </div> - <!----> - <!----> - <!----> - <!----> - <!----> - </div> - </div> </div> </div> <!----> diff --git a/packages/ui/src/components/titre.stories_snapshots_BonEspoirProlongation2.html b/packages/ui/src/components/titre.stories_snapshots_BonEspoirProlongation2.html index fd0a69a20..7abfc01c7 100644 --- a/packages/ui/src/components/titre.stories_snapshots_BonEspoirProlongation2.html +++ b/packages/ui/src/components/titre.stories_snapshots_BonEspoirProlongation2.html @@ -342,7 +342,7 @@ </div> </div> <div style="display: flex;"> - <div class="fr-text--md">Surface : 122.275 Km²</div><a class="fr-btn fr-btn--secondary fr-btn--icon-right fr-icon-download-line" title="Télécharge les points au format csv" href="data:text/csv;charset=utf-8,nom;description;longitude;latitude;x_deg;y_deg%0AA;;-53.9577777777778;5.07666666666667;-53%C2%B057,467';5%C2%B04,6'%0AB;;-53.8763888888889;5.02277777777778;-53%C2%B052,583';5%C2%B01,367'%0AC;;-53.7322222222222;5.02361111111111;-53%C2%B043,933';5%C2%B01,417'%0AD;;-53.7138888888889;4.96388888888889;-53%C2%B042,833';4%C2%B057,833'%0AE;;-53.8208333333333;4.97972222222222;-53%C2%B049,25';4%C2%B058,783'%0AF;;-53.8944444444444;5.00055555555556;-53%C2%B053,667';5%C2%B00,033'%0AG;;-53.9575;5.0325;-53%C2%B057,45';5%C2%B01,95'" download="points-m-pr-bon-espoir-2001.csv" style="margin-left: auto;">.csv</a> + <div class="fr-text--md">Surface : 122.14 Km²</div><a class="fr-btn fr-btn--secondary fr-btn--icon-right fr-icon-download-line" title="Télécharge les points au format csv" href="data:text/csv;charset=utf-8,nom;description;longitude;latitude;x_deg;y_deg%0AA;;-53.9577777777778;5.07666666666667;-53%C2%B057,467';5%C2%B04,6'%0AB;;-53.8763888888889;5.02277777777778;-53%C2%B052,583';5%C2%B01,367'%0AC;;-53.7322222222222;5.02361111111111;-53%C2%B043,933';5%C2%B01,417'%0AD;;-53.7138888888889;4.96388888888889;-53%C2%B042,833';4%C2%B057,833'%0AE;;-53.8208333333333;4.97972222222222;-53%C2%B049,25';4%C2%B058,783'%0AF;;-53.8944444444444;5.00055555555556;-53%C2%B053,667';5%C2%B00,033'%0AG;;-53.9575;5.0325;-53%C2%B057,45';5%C2%B01,95'" download="points-m-pr-bon-espoir-2001.csv" style="margin-left: auto;">.csv</a> </div> </div> <!----> @@ -609,10 +609,193 @@ </div> </div> <!----> - <!----> + <div> + <div class="fr-text--sm fr-mb-0">Surface</div> + <div class="fr-text--md fr-mb-0" style="font-weight: 500;">122,14 km² environ</div> + </div> <!----> </div> - <!----> + <div class="fr-pt-2w"> + <div class="fr-tabs" style="--tabs-height: 0px;"> + <ul class="fr-tabs__list" role="tablist" aria-label="Affichage des titres en vue carte ou tableau"> + <li role="presentation"><button id="tabpanel-carte-iV47juaOeL4EAUsOqiWN6gOO" class="fr-tabs__tab fr-icon-earth-fill fr-tabs__tab--icon-left" tabindex="-1" role="tab" aria-label="Carte" aria-selected="false" aria-controls="tabpanel-carte-iV47juaOeL4EAUsOqiWN6gOO-panel">Carte</button></li> + <li role="presentation"><button id="tabpanel-points-iV47juaOeL4EAUsOqiWN6gOO" class="fr-tabs__tab fr-icon-list-unordered fr-tabs__tab--icon-left" tabindex="0" role="tab" aria-label="Tableau" aria-selected="true" aria-controls="tabpanel-points-iV47juaOeL4EAUsOqiWN6gOO-panel">Tableau</button></li> + </ul> + <div id="tabpanel-carte-iV47juaOeL4EAUsOqiWN6gOO-panel" class="fr-tabs__panel fr-tabs__panel--direction-start" role="tabpanel" aria-labelledby="tabpanel-carte-iV47juaOeL4EAUsOqiWN6gOO" tabindex="0"> + <!----> + </div> + <div id="tabpanel-points-iV47juaOeL4EAUsOqiWN6gOO-panel" class="fr-tabs__panel fr-tabs__panel--selected" role="tabpanel" aria-labelledby="tabpanel-points-iV47juaOeL4EAUsOqiWN6gOO" tabindex="0"> + <div style="display: flex; flex-direction: column;"> + <div class="fr-select-group"><label class="fr-label" for="4326">Système géographique</label> + <div id="4326_wrapper" class="_typeahead_8eddf1"> + <div class="flex"><input id="4326" type="text" title="" name="4326" disabled="" class="fr-input" placeholder="" autocomplete="off" role="combobox" aria-controls="4326-control" aria-activedescendant="4326-control" aria-expanded="false" aria-autocomplete="list" value="WGS84 - (4326)"></div> + <ul class="_typeahead-list_8eddf1 " tabindex="-1" id="4326-control" role="listbox"> + <li class="_typeahead-list-item_8eddf1 _typeahead-list-item-active_8eddf1" aria-selected="false" id="4326-control-0"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="fr-text--bold">Mayotte 2004 / UTM zone 38S - (4471)</span><span class="fr-text">Mayotte - à terre et extraterritorial</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-1"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="fr-text--bold">Réunion / UTM zone 40S - (2975)</span><span class="fr-text">Réunion</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-2"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="fr-text--bold">RGAF09 / UTM zone 20N - (5490)</span><span class="fr-text">Antilles françaises à terre et extraterritorial à l'ouest du méridien 60° Ouest - Guadeloupe (incluant Grande Terre, Basse Terre, Marie Galante, Les Saintes, Iles de la Petite Terre, La Desirade, St Barthélemy, partie nord de St Martin) et Martinique.</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-3"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="fr-text--bold">RGF93 / Lambert-93 - (2154)</span><span class="fr-text">France - à terre et extraterritorial - continentale et Corse.</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-4"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="fr-text--bold">RGFG95 / UTM zone 22N - (2972)</span><span class="fr-text">Guyane française - à terre et extraterritorial.</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-5"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="fr-text--bold">St Pierre et Miquelon / UTM zone 21N - (4467)</span><span class="fr-text">St Pierre et Miquelon à terre et extraterritorial</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-6"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">ED50 - (4230)</span><span class="fr-text">Europe</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-7"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">Guadeloupe 1948 / UTM zone 20N - (2970)</span><span class="fr-text">Guadeloupe - à terre - Basse-Terre, Grande-Terre, La Desirade, Marie-Galante, Les Saintes.</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-8"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">NTF (Greenwich) - (4275)</span><span class="fr-text">France - à terre - continentale et Corse.</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-9"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">NTF (Paris) - (4807)</span><span class="fr-text">France - à terre - continentale et Corse.</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-10"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">NTF (Paris) / Lambert Nord France - (27561)</span><span class="fr-text">France - continentale au nord de 53,5 grades North (48°09'N).</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-11"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">NTF (Paris) / Lambert Sud france - (27563)</span><span class="fr-text">France - continentale au sud de 50,5 grades nord (45°27'N).</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-12"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">NTF (Paris) / Lambert zone I - (27571)</span><span class="fr-text">France - continentale au nord de 53,5 grades nord (48°09'N).</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-13"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">NTF (Paris) / Lambert zone II - (27572)</span><span class="fr-text">France - continentale entre 45°27'N et 48°09'N.</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-14"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">NTF (Paris) / Lambert zone III - (27573)</span><span class="fr-text">France - continentale au sud de 50,5 grades nord (45°27'N).</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-15"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">RGF93 - (4171)</span><span class="fr-text">France - à terre et extraterritorial - continentale et Corse.</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-16"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">RGF93 / CC49 - (3949)</span><span class="fr-text">France - continentale entre 48°N et 50°N.</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-17"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">RGFG95 - (4624)</span><span class="fr-text">Guyane Française - à terre et extraterritorial.</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-18"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">RGFG95 / UTM zone 21N - (3313)</span><span class="fr-text">Guyane française - à terre et extraterritorial.</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-19"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">WGS84 / UTM zone 20N - (32620)</span><span class="fr-text">Hémisphère Nord - entre 66°W et 60°W</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-20"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">WGS84 / UTM zone 21N - (32621)</span><span class="fr-text">Hémisphère Nord - entre 60°W et 54°W</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-21"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">WGS84 / UTM zone 22N - (32622)</span><span class="fr-text">Hémisphère Nord - entre 54°W et 48°W</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-22"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">WGS84 / UTM zone 30N - (32630)</span><span class="fr-text">Hémisphère Nord - entre 6°W et 0°W</span></div> + </li> + <li class="_typeahead-list-item_8eddf1 " aria-selected="false" id="4326-control-23"> + <div style="display: flex; flex-direction: column;" class="fr-pl-2w"><span class="">WGS84 / UTM zone 31N - (32631)</span><span class="fr-text">Hémisphère Nord - entre 0°E et 6°E</span></div> + </li> + </ul> + </div> + </div> + <div style="display: flex; flex-direction: column;"> + <div class="fr-mb-1w"> + <div class="fr-table fr-table--no-scroll" style="overflow: auto;"> + <div class="fr-table__wrapper" style="width: auto;"> + <div class="fr-table__container"> + <div class="fr-table__content"> + <table style="display: table; width: 100%;"> + <caption>Points</caption> + <thead> + <tr> + <th scope="col">Nom du point</th> + <th scope="col">Description</th> + <th scope="col">Longitude</th> + <th scope="col">Latitude</th> + <th scope="col">Longitude (E)</th> + <th scope="col">Latitude (N)</th> + </tr> + </thead> + <tbody> + <tr> + <td><span class="">A</span></td> + <td><span class=""></span></td> + <td><span class="">-53.9577777777778</span></td> + <td><span class="">5.07666666666667</span></td> + <td><span class="">-53°57,467'</span></td> + <td><span class="">5°4,6'</span></td> + </tr> + <tr> + <td><span class="">B</span></td> + <td><span class=""></span></td> + <td><span class="">-53.8763888888889</span></td> + <td><span class="">5.02277777777778</span></td> + <td><span class="">-53°52,583'</span></td> + <td><span class="">5°1,367'</span></td> + </tr> + <tr> + <td><span class="">C</span></td> + <td><span class=""></span></td> + <td><span class="">-53.7322222222222</span></td> + <td><span class="">5.02361111111111</span></td> + <td><span class="">-53°43,933'</span></td> + <td><span class="">5°1,417'</span></td> + </tr> + <tr> + <td><span class="">D</span></td> + <td><span class=""></span></td> + <td><span class="">-53.7138888888889</span></td> + <td><span class="">4.96388888888889</span></td> + <td><span class="">-53°42,833'</span></td> + <td><span class="">4°57,833'</span></td> + </tr> + <tr> + <td><span class="">E</span></td> + <td><span class=""></span></td> + <td><span class="">-53.8208333333333</span></td> + <td><span class="">4.97972222222222</span></td> + <td><span class="">-53°49,25'</span></td> + <td><span class="">4°58,783'</span></td> + </tr> + <tr> + <td><span class="">F</span></td> + <td><span class=""></span></td> + <td><span class="">-53.8944444444444</span></td> + <td><span class="">5.00055555555556</span></td> + <td><span class="">-53°53,667'</span></td> + <td><span class="">5°0,033'</span></td> + </tr> + <tr> + <td><span class="">G</span></td> + <td><span class=""></span></td> + <td><span class="">-53.9575</span></td> + <td><span class="">5.0325</span></td> + <td><span class="">-53°57,45'</span></td> + <td><span class="">5°1,95'</span></td> + </tr> + </tbody> + </table> + </div> + </div> + </div> + </div> + </div> + <div style="display: flex;"> + <div class="fr-text--md">Surface : 122.14 Km²</div><a class="fr-btn fr-btn--secondary fr-btn--icon-right fr-icon-download-line" title="Télécharge les points au format csv" href="data:text/csv;charset=utf-8,nom;description;longitude;latitude;x_deg;y_deg%0AA;;-53.9577777777778;5.07666666666667;-53%C2%B057,467';5%C2%B04,6'%0AB;;-53.8763888888889;5.02277777777778;-53%C2%B052,583';5%C2%B01,367'%0AC;;-53.7322222222222;5.02361111111111;-53%C2%B043,933';5%C2%B01,417'%0AD;;-53.7138888888889;4.96388888888889;-53%C2%B042,833';4%C2%B057,833'%0AE;;-53.8208333333333;4.97972222222222;-53%C2%B049,25';4%C2%B058,783'%0AF;;-53.8944444444444;5.00055555555556;-53%C2%B053,667';5%C2%B00,033'%0AG;;-53.9575;5.0325;-53%C2%B057,45';5%C2%B01,95'" download="points-m-pr-bon-espoir-2001.csv" style="margin-left: auto;">.csv</a> + </div> + </div> + <!----> + </div> + </div> + </div> + </div> <!----> <!----> <!----> diff --git a/packages/ui/src/components/titre.stories_snapshots_ChantepieMutation.html b/packages/ui/src/components/titre.stories_snapshots_ChantepieMutation.html index 4a19fbb8e..ad524a8d4 100644 --- a/packages/ui/src/components/titre.stories_snapshots_ChantepieMutation.html +++ b/packages/ui/src/components/titre.stories_snapshots_ChantepieMutation.html @@ -19,7 +19,7 @@ <div class="fr-mt-2w">Références<div style="font-weight: 500;">DEB : 2013-0224-MI</div> </div> <div class="fr-grid-row fr-grid-row--middle fr-mt-4w"> - <div><span class="fr-icon-calendar-line fr-icon--sm fr-mr-1w" style="color: var(--text-title-blue-france);" aria-hidden="true"></span>Modifié le 12-10-2023</div><a href="/mocked-href" title="Journaux du titre" class="fr-link" aria-label="Journaux du titre" style="margin-left: auto;">Journaux du titre</a> + <!----><a href="/mocked-href" title="Journaux du titre" class="fr-link" aria-label="Journaux du titre" style="margin-left: auto;">Journaux du titre</a> </div> <div> <!----> diff --git a/packages/ui/src/components/titre.stories_snapshots_ChantepieOctroi.html b/packages/ui/src/components/titre.stories_snapshots_ChantepieOctroi.html index 9173dcdef..2c9f7dd12 100644 --- a/packages/ui/src/components/titre.stories_snapshots_ChantepieOctroi.html +++ b/packages/ui/src/components/titre.stories_snapshots_ChantepieOctroi.html @@ -19,7 +19,7 @@ <div class="fr-mt-2w">Références<div style="font-weight: 500;">DEB : 2013-0224-MI</div> </div> <div class="fr-grid-row fr-grid-row--middle fr-mt-4w"> - <div><span class="fr-icon-calendar-line fr-icon--sm fr-mr-1w" style="color: var(--text-title-blue-france);" aria-hidden="true"></span>Modifié le 12-10-2023</div> + <!----> <!----> </div> <div> diff --git a/packages/ui/src/components/titre.stories_snapshots_CriqueAdolpheOctroi.html b/packages/ui/src/components/titre.stories_snapshots_CriqueAdolpheOctroi.html index 6841a78b9..91034fa09 100644 --- a/packages/ui/src/components/titre.stories_snapshots_CriqueAdolpheOctroi.html +++ b/packages/ui/src/components/titre.stories_snapshots_CriqueAdolpheOctroi.html @@ -20,7 +20,7 @@ <div style="font-weight: 500;">ONF : AR 2022-027</div> </div> <div class="fr-grid-row fr-grid-row--middle fr-mt-4w"> - <div><span class="fr-icon-calendar-line fr-icon--sm fr-mr-1w" style="color: var(--text-title-blue-france);" aria-hidden="true"></span>Modifié le 20-10-2023</div><a href="/mocked-href" title="Journaux du titre" class="fr-link" aria-label="Journaux du titre" style="margin-left: auto;">Journaux du titre</a> + <!----><a href="/mocked-href" title="Journaux du titre" class="fr-link" aria-label="Journaux du titre" style="margin-left: auto;">Journaux du titre</a> </div> <div> <!----> @@ -69,7 +69,7 @@ <h2 style="margin: 0px;">Octroi</h2> <p style="z-index: unset; margin-bottom: 0px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; margin-right: auto;" class="fr-badge fr-badge--md fr-ml-2w fr-badge--green-bourgeon fr-ml-2w" title="accepté" aria-label="accepté">accepté</p><button class="fr-btn fr-btn--primary fr-btn--md" title="Ajouter une démarche" aria-label="Ajouter une démarche" type="button">Ajouter une démarche</button><button class="fr-btn fr-btn--secondary fr-btn--md fr-icon-pencil-line fr-ml-2w" title="Modifier la description" aria-label="Modifier la description" type="button" style="margin-right: 0px;"> <!----> - </button><button class="fr-btn fr-btn--secondary fr-btn--md fr-icon-delete-bin-line fr-ml-2w" title="Supprimer la démarche ArmOct" aria-label="Supprimer la démarche ArmOct" type="button"> + </button><button class="fr-btn fr-btn--secondary fr-btn--md fr-icon-delete-bin-line fr-ml-2w" title="Supprimer la démarche AncienLogigrammeOctroiARM" aria-label="Supprimer la démarche AncienLogigrammeOctroiARM" type="button"> <!----> </button> </div> diff --git a/packages/ui/src/components/titre.stories_snapshots_Lenoncourt.html b/packages/ui/src/components/titre.stories_snapshots_Lenoncourt.html index 74b005837..ac0d54b59 100644 --- a/packages/ui/src/components/titre.stories_snapshots_Lenoncourt.html +++ b/packages/ui/src/components/titre.stories_snapshots_Lenoncourt.html @@ -42,9 +42,12 @@ <li class="_hidden_b2e482"><a href="/mocked-href" title="Voir la phase Mutation du 19-11-1970" aria-label="Voir la phase Mutation du 19-11-1970" tab-index="-1">Voir la phase Mutation du 19-11-1970</a></li> <li class="_hidden_b2e482"><a href="/mocked-href" title="Voir la phase Mutation du 27-11-1975" aria-label="Voir la phase Mutation du 27-11-1975" tab-index="-1">Voir la phase Mutation du 27-11-1975</a></li> <li class="_hidden_b2e482"><a href="/mocked-href" title="Voir la phase Extension de périmètre du 13-09-1981" aria-label="Voir la phase Extension de périmètre du 13-09-1981" tab-index="-1">Voir la phase Extension de périmètre du 13-09-1981</a></li> + <li class="_hidden_b2e482"><a href="/mocked-href" title="Voir l'événement Autorisation d'ouverture de travaux du 2000-06-07 lié à la phase Extension de périmètre" aria-label="Voir l'événement Autorisation d'ouverture de travaux du 2000-06-07 lié à la phase Extension de périmètre" tab-index="-1">Voir l'événement Autorisation d'ouverture de travaux du 07-06-2000 lié à la phase Extension de périmètre</a></li> <li class="_hidden_b2e482"><a href="/mocked-href" title="Voir la phase Mutation du 06-10-2000" aria-label="Voir la phase Mutation du 06-10-2000" tab-index="-1">Voir la phase Mutation du 06-10-2000</a></li> <li class="_hidden_b2e482"><a href="/mocked-href" title="Voir la phase Mutation du 08-01-2003" aria-label="Voir la phase Mutation du 08-01-2003" tab-index="-1">Voir la phase Mutation du 08-01-2003</a></li> <li class="_hidden_b2e482"><a href="/mocked-href" title="Voir la phase Mutation du 28-02-2004" aria-label="Voir la phase Mutation du 28-02-2004" tab-index="-1">Voir la phase Mutation du 28-02-2004</a></li> + <li class="_hidden_b2e482"><a href="/mocked-href" title="Voir l'événement Autorisation d'ouverture de travaux du 2012-05-15 lié à la phase Mutation" aria-label="Voir l'événement Autorisation d'ouverture de travaux du 2012-05-15 lié à la phase Mutation" tab-index="-1">Voir l'événement Autorisation d'ouverture de travaux du 15-05-2012 lié à la phase Mutation</a></li> + <li class="_hidden_b2e482"><a href="/mocked-href" title="Voir l'événement Autorisation d'ouverture de travaux du 2019-05-31 lié à la phase Mutation" aria-label="Voir l'événement Autorisation d'ouverture de travaux du 2019-05-31 lié à la phase Mutation" tab-index="-1">Voir l'événement Autorisation d'ouverture de travaux du 31-05-2019 lié à la phase Mutation</a></li> <li class="_hidden_b2e482"><a href="/mocked-href" title="Voir la phase Prolongation du 01-03-2024" aria-label="Voir la phase Prolongation du 01-03-2024" tab-index="-1">Voir la phase Prolongation du 01-03-2024</a></li> <li class="_hidden_b2e482"><a href="/mocked-href" title="Voir la phase Extension de périmètre du 01-03-2024" aria-label="Voir la phase Extension de périmètre du 01-03-2024" aria-current="page" tab-index="-1">Voir la phase Extension de périmètre du 01-03-2024</a></li> </ul> @@ -62,7 +65,16 @@ </div> <div style="display: flex; width: 100%;"> <div style="display: flex; gap: 5px; position: relative; height: 20px; flex: 1;"> - <div class="_phasesContainer_b2e482" style="flex: 1;"><a tabindex="-1" href="/mocked-href" title="Octroi" class="_phase_b2e482" aria-label="Octroi" style="min-width: 200px;"></a><a tabindex="-1" href="/mocked-href" title="Mutation" class="_phase_b2e482" aria-label="Mutation" style="min-width: 200px;"></a><a tabindex="-1" href="/mocked-href" title="Mutation" class="_phase_b2e482" aria-label="Mutation" style="min-width: 200px;"></a><a tabindex="-1" href="/mocked-href" title="Extension de périmètre" class="_phase_b2e482" aria-label="Extension de périmètre" style="min-width: 200px;"></a><a tabindex="-1" href="/mocked-href" title="Mutation" class="_phase_b2e482" aria-label="Mutation" style="min-width: 200px;"></a><a tabindex="-1" href="/mocked-href" title="Mutation" class="_phase_b2e482" aria-label="Mutation" style="min-width: 200px;"></a><a tabindex="-1" href="/mocked-href" title="Mutation" class="_phase_b2e482" aria-label="Mutation" style="min-width: 200px;"></a></div> + <div class="_phasesContainer_b2e482" style="flex: 1;"><a tabindex="-1" href="/mocked-href" title="Octroi" class="_phase_b2e482" aria-label="Octroi" style="min-width: 200px;"></a><a tabindex="-1" href="/mocked-href" title="Mutation" class="_phase_b2e482" aria-label="Mutation" style="min-width: 200px;"></a><a tabindex="-1" href="/mocked-href" title="Mutation" class="_phase_b2e482" aria-label="Mutation" style="min-width: 200px;"></a><a tabindex="-1" href="/mocked-href" title="Extension de périmètre" class="_phase_b2e482" aria-label="Extension de périmètre" style="min-width: 200px;"><a tabindex="-1" href="/mocked-href" title="Autorisation d'ouverture de travaux" aria-label="Autorisation d'ouverture de travaux" aria-describedby="timeline-event-m-cx-lenoncourt-1968-aom01"><svg class="_travaux-icone_a26566" width="17" height="19" viewBox="0 0 17 19" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M0.647766 17.0224L2.06999 17.0223L6.7467 0.275378C6.79229 0.110124 7.12833 0 7.29173 0H9.62077V0.00185531C9.78417 0.00185531 10.048 0.110124 10.0938 0.275378L14.7759 17.0223H16.2624C16.6195 17.0223 16.9103 17.2312 16.9103 17.4858V18.5364C16.9103 18.791 16.6177 19 16.2624 19L0.647905 18.9999C0.290774 18.9999 0 18.7909 0 18.5363V17.4857C0 17.2293 0.292467 17.0224 0.647766 17.0224ZM6.96092 2.97703H9.9531L9.33753 0.746577H7.57446L6.96092 2.97703ZM11.0113 6.82042H5.90076L5.0896 9.76317H11.8261L11.0113 6.82042ZM12.8844 13.6065H4.02757L3.08523 17.0224H13.8267L12.8844 13.6065Z" fill="none"></path> + <path d="M0.647766 17.0224L2.06999 17.0223L6.7467 0.275378C6.79229 0.110124 7.12833 0 7.29173 0H9.62077V0.00185531C9.78417 0.00185531 10.048 0.110124 10.0938 0.275378L14.7759 17.0223H16.2624C16.6195 17.0223 16.9103 17.2312 16.9103 17.4858V18.5364C16.9103 18.791 16.6177 19 16.2624 19L0.647905 18.9999C0.290774 18.9999 0 18.7909 0 18.5363V17.4857C0 17.2293 0.292467 17.0224 0.647766 17.0224ZM6.96092 2.97703H9.9531L9.33753 0.746577H7.57446L6.96092 2.97703ZM11.0113 6.82042H5.90076L5.0896 9.76317H11.8261L11.0113 6.82042ZM12.8844 13.6065H4.02757L3.08523 17.0224H13.8267L12.8844 13.6065Z" stroke="black"></path> + </svg></a></a><a tabindex="-1" href="/mocked-href" title="Mutation" class="_phase_b2e482" aria-label="Mutation" style="min-width: 200px;"></a><a tabindex="-1" href="/mocked-href" title="Mutation" class="_phase_b2e482" aria-label="Mutation" style="min-width: 200px;"></a><a tabindex="-1" href="/mocked-href" title="Mutation" class="_phase_b2e482" aria-label="Mutation" style="min-width: 200px;"><a tabindex="-1" href="/mocked-href" title="Autorisation d'ouverture de travaux" aria-label="Autorisation d'ouverture de travaux" aria-describedby="timeline-event-m-cx-lenoncourt-1968-aom02"><svg class="_travaux-icone_a26566" width="17" height="19" viewBox="0 0 17 19" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M0.647766 17.0224L2.06999 17.0223L6.7467 0.275378C6.79229 0.110124 7.12833 0 7.29173 0H9.62077V0.00185531C9.78417 0.00185531 10.048 0.110124 10.0938 0.275378L14.7759 17.0223H16.2624C16.6195 17.0223 16.9103 17.2312 16.9103 17.4858V18.5364C16.9103 18.791 16.6177 19 16.2624 19L0.647905 18.9999C0.290774 18.9999 0 18.7909 0 18.5363V17.4857C0 17.2293 0.292467 17.0224 0.647766 17.0224ZM6.96092 2.97703H9.9531L9.33753 0.746577H7.57446L6.96092 2.97703ZM11.0113 6.82042H5.90076L5.0896 9.76317H11.8261L11.0113 6.82042ZM12.8844 13.6065H4.02757L3.08523 17.0224H13.8267L12.8844 13.6065Z" fill="none"></path> + <path d="M0.647766 17.0224L2.06999 17.0223L6.7467 0.275378C6.79229 0.110124 7.12833 0 7.29173 0H9.62077V0.00185531C9.78417 0.00185531 10.048 0.110124 10.0938 0.275378L14.7759 17.0223H16.2624C16.6195 17.0223 16.9103 17.2312 16.9103 17.4858V18.5364C16.9103 18.791 16.6177 19 16.2624 19L0.647905 18.9999C0.290774 18.9999 0 18.7909 0 18.5363V17.4857C0 17.2293 0.292467 17.0224 0.647766 17.0224ZM6.96092 2.97703H9.9531L9.33753 0.746577H7.57446L6.96092 2.97703ZM11.0113 6.82042H5.90076L5.0896 9.76317H11.8261L11.0113 6.82042ZM12.8844 13.6065H4.02757L3.08523 17.0224H13.8267L12.8844 13.6065Z" stroke="black"></path> + </svg></a><a tabindex="-1" href="/mocked-href" title="Autorisation d'ouverture de travaux" aria-label="Autorisation d'ouverture de travaux" aria-describedby="timeline-event-m-cx-lenoncourt-1968-aom03"><svg class="_travaux-icone_a26566" width="17" height="19" viewBox="0 0 17 19" fill="none" xmlns="http://www.w3.org/2000/svg"> + <path d="M0.647766 17.0224L2.06999 17.0223L6.7467 0.275378C6.79229 0.110124 7.12833 0 7.29173 0H9.62077V0.00185531C9.78417 0.00185531 10.048 0.110124 10.0938 0.275378L14.7759 17.0223H16.2624C16.6195 17.0223 16.9103 17.2312 16.9103 17.4858V18.5364C16.9103 18.791 16.6177 19 16.2624 19L0.647905 18.9999C0.290774 18.9999 0 18.7909 0 18.5363V17.4857C0 17.2293 0.292467 17.0224 0.647766 17.0224ZM6.96092 2.97703H9.9531L9.33753 0.746577H7.57446L6.96092 2.97703ZM11.0113 6.82042H5.90076L5.0896 9.76317H11.8261L11.0113 6.82042ZM12.8844 13.6065H4.02757L3.08523 17.0224H13.8267L12.8844 13.6065Z" fill="none"></path> + <path d="M0.647766 17.0224L2.06999 17.0223L6.7467 0.275378C6.79229 0.110124 7.12833 0 7.29173 0H9.62077V0.00185531C9.78417 0.00185531 10.048 0.110124 10.0938 0.275378L14.7759 17.0223H16.2624C16.6195 17.0223 16.9103 17.2312 16.9103 17.4858V18.5364C16.9103 18.791 16.6177 19 16.2624 19L0.647905 18.9999C0.290774 18.9999 0 18.7909 0 18.5363V17.4857C0 17.2293 0.292467 17.0224 0.647766 17.0224ZM6.96092 2.97703H9.9531L9.33753 0.746577H7.57446L6.96092 2.97703ZM11.0113 6.82042H5.90076L5.0896 9.76317H11.8261L11.0113 6.82042ZM12.8844 13.6065H4.02757L3.08523 17.0224H13.8267L12.8844 13.6065Z" stroke="black"></path> + </svg></a></a></div> <div style="border: 2px solid black;"></div> <div class="_phasesContainer_b2e482" style="flex: 1;"><a tabindex="-1" href="/mocked-href" title="Prolongation" class="_phase_b2e482" aria-label="Prolongation" style="min-width: 200px;"></a><a tabindex="-1" href="/mocked-href" title="Extension de périmètre" class="_phase_b2e482" aria-label="Extension de périmètre" aria-current="page" style="min-width: 200px;"></a></div> <!----> @@ -142,7 +154,7 @@ <!----> <div style="grid-column: 1 / -1;"> <div class="fr-text--sm fr-mb-0">Communes</div> - <div class="fr-text--md fr-mb-0" style="font-weight: 500;">Saulxures-lès-Nancy, Lenoncourt, Cerville, Art-sur-Meurthe</div> + <div class="fr-text--md fr-mb-0" style="font-weight: 500;">Art-sur-Meurthe, Cerville, Lenoncourt, Saulxures-lès-Nancy</div> </div> </div> </div> diff --git a/packages/ui/src/components/titre.tsx b/packages/ui/src/components/titre.tsx index 89cb0601e..5f1218797 100644 --- a/packages/ui/src/components/titre.tsx +++ b/packages/ui/src/components/titre.tsx @@ -1,7 +1,7 @@ import { computed, defineComponent, onMounted, ref, watch, inject } from 'vue' import { useRouter } from 'vue-router' import { LoadingElement } from './_ui/functional-loader' -import { demarcheEnregistrementDemandeDateFind, DemarcheEtapeFondamentale, DemarcheSlug, demarcheSlugValidator } from 'camino-common/src/demarche' +import { DemarcheEtapeFondamentale, DemarcheId, DemarcheSlug, demarcheSlugValidator } from 'camino-common/src/demarche' import { AsyncData, CaminoHttpError } from '@/api/client-rest' import { User, isAdministration, isEntrepriseOrBureauDEtude, isSuper } from 'camino-common/src/roles' import { capitalize } from 'camino-common/src/strings' @@ -43,17 +43,35 @@ import { ModifiedDate } from './_common/modified-date' import { DemarcheMiseEnConcurrence } from './titre/demarche-mise-en-concurrence' import { DemarchesConsentement } from './titre/demarche-consentement' import { useState } from '@/utils/vue-tsx-utils' -import { isMachineWithConsentement, machineIdFind } from 'camino-common/src/machines' +import { isMachineWithConsentement, MachineInfo } from 'camino-common/src/machines' import { InitialSort } from './_ui/table' import { HTTP_STATUS } from 'camino-common/src/http' import { fr } from '@codegouvfr/react-dsfr' import { TitreVisibilite } from './_common/titre-visibilite' +import { CaminoError } from 'camino-common/src/zod-tools' const activitesSort: InitialSort<string> = { colonne: activitesColonneIdAnnee, ordre: 'desc', } +const getMachinesInfo = (titre: TitreGet): Record<DemarcheId, MachineInfo> | CaminoError<string> => { + const result = titre.demarches.map(demarche => MachineInfo.withMachineId(titre.titre_type_id, demarche.demarche_type_id, demarche.id, demarche.machine_id)) + + const error = result.find(machineInfo => !machineInfo.valid) + if (isNotNullNorUndefined(error)) { + return { message: error.error } + } else { + return result.reduce<Record<DemarcheId, MachineInfo>>((acc, machineInfo) => { + if (machineInfo.valid) { + acc[machineInfo.value.demarcheId] = machineInfo.value + } + + return acc + }, {}) + } +} + export const Titre = defineComponent(() => { const router = useRouter() @@ -130,11 +148,11 @@ export interface Props { } export const PureTitre = defineComponent<Props>(props => { - const titreData = ref<AsyncData<TitreGet>>({ status: 'LOADING' }) + const titreData = ref<AsyncData<{ titre: TitreGet; machinesInfo: Record<DemarcheId, MachineInfo> }>>({ status: 'LOADING' }) const [hasTitresFrom, setHasTitresFrom] = useState<boolean | 'LOADING'>('LOADING') const retrieveTitre = async () => { - const titreId: TitreId | null = titreData.value.status === 'LOADED' ? titreData.value.value.id : null + const titreId: TitreId | null = titreData.value.status === 'LOADED' ? titreData.value.value.titre.id : null if (titreId !== null) { await updateTitre(titreId) } @@ -163,22 +181,28 @@ export const PureTitre = defineComponent<Props>(props => { } else { try { const data = await props.apiClient.getTitreById(titreIdOrSlug) - titreData.value = { status: 'LOADED', value: data } - - let demarcheSlug = props.currentDemarcheSlug - - if (isNullOrUndefinedOrEmpty(demarcheSlug) && 'erreur' in phases.value) { - demarcheSlug = phases.value.demarches[0].slug - } else if ( - (isNullOrUndefinedOrEmpty(demarcheSlug) || isNullOrUndefined(data.demarches.find(({ slug }) => slug === props.currentDemarcheSlug))) && - !('erreur' in phases.value) && - phases.value.length > 0 - ) { - demarcheSlug = phases.value[phases.value.length - 1][phases.value[phases.value.length - 1].length - 1].slug - } + const machinesInfo = getMachinesInfo(data) - if (data.slug !== props.titreIdOrSlug || demarcheSlug !== props.currentDemarcheSlug) { - props.router.replace({ name: 'titre', params: { id: data.slug }, query: { demarcheSlug } }) + if ('message' in machinesInfo) { + titreData.value = { status: 'NEW_ERROR', error: machinesInfo } + } else { + titreData.value = { status: 'LOADED', value: { titre: data, machinesInfo } } + + let demarcheSlug = props.currentDemarcheSlug + + if (isNullOrUndefinedOrEmpty(demarcheSlug) && 'erreur' in phases.value) { + demarcheSlug = phases.value.demarches[0].slug + } else if ( + (isNullOrUndefinedOrEmpty(demarcheSlug) || isNullOrUndefined(data.demarches.find(({ slug }) => slug === props.currentDemarcheSlug))) && + !('erreur' in phases.value) && + phases.value.length > 0 + ) { + demarcheSlug = phases.value[phases.value.length - 1][phases.value[phases.value.length - 1].length - 1].slug + } + + if (data.slug !== props.titreIdOrSlug || demarcheSlug !== props.currentDemarcheSlug) { + props.router.replace({ name: 'titre', params: { id: data.slug }, query: { demarcheSlug } }) + } } } catch (e: any) { console.error('error', e) @@ -200,7 +224,7 @@ export const PureTitre = defineComponent<Props>(props => { watch( () => props.titreIdOrSlug, async (_newValue, _oldValue) => { - if (titreData.value.status !== 'LOADED' || (titreData.value.value.id !== props.titreIdOrSlug && titreData.value.value.slug !== props.titreIdOrSlug)) { + if (titreData.value.status !== 'LOADED' || (titreData.value.value.titre.id !== props.titreIdOrSlug && titreData.value.value.titre.slug !== props.titreIdOrSlug)) { await updateTitre(props.titreIdOrSlug) } } @@ -210,10 +234,15 @@ export const PureTitre = defineComponent<Props>(props => { () => titreData.value, async () => { if (titreData.value.status === 'LOADED') { - const titre = titreData.value.value + const titre = titreData.value.value.titre showActivitesLink.value = - canHaveActivites({ titreTypeId: titreData.value.value.titre_type_id, communes: communes.value, secteursMaritime: secteursMaritime.value, demarches: titreData.value.value.demarches }) && + canHaveActivites({ + titreTypeId: titreData.value.value.titre.titre_type_id, + communes: communes.value, + secteursMaritime: secteursMaritime.value, + demarches: titreData.value.value.titre.demarches, + }) && (await canReadTitreActivites( props.user, () => Promise.resolve(titre.titre_type_id), @@ -263,8 +292,8 @@ export const PureTitre = defineComponent<Props>(props => { const showActivitesLink = ref<boolean>(false) const perimetre = computed<null | DemarcheEtapeFondamentale['fondamentale']['perimetre']>(() => { - if (titreData.value.status === 'LOADED' && titreData.value.value.demarches !== null) { - return getMostRecentValuePropFromEtapeFondamentaleValide('perimetre', titreData.value.value.demarches) + if (titreData.value.status === 'LOADED' && titreData.value.value.titre.demarches !== null) { + return getMostRecentValuePropFromEtapeFondamentaleValide('perimetre', titreData.value.value.titre.demarches) } return null @@ -281,8 +310,8 @@ export const PureTitre = defineComponent<Props>(props => { : [] const administrationGestionnaires = - titreData.value.value.titre_type_id !== null - ? getGestionnairesByTitreTypeId(titreData.value.value.titre_type_id) + titreData.value.value.titre.titre_type_id !== null + ? getGestionnairesByTitreTypeId(titreData.value.value.titre.titre_type_id) .filter(({ associee }) => !associee) .filter(({ administrationId }) => Administrations[administrationId].typeId === ADMINISTRATION_TYPE_IDS.MINISTERE) .map(({ administrationId }) => administrationId) @@ -312,7 +341,7 @@ export const PureTitre = defineComponent<Props>(props => { const titreLinkFormTitre = computed(() => { if (titreData.value.status === 'LOADED') { - return { id: titreData.value.value.id, typeId: titreData.value.value.titre_type_id, administrations: administrations.value, demarches: titreData.value.value.demarches } + return { id: titreData.value.value.titre.id, typeId: titreData.value.value.titre.titre_type_id, administrations: administrations.value, demarches: titreData.value.value.titre.demarches } } return null @@ -320,7 +349,7 @@ export const PureTitre = defineComponent<Props>(props => { const phases = computed<PhaseWithAlterations>(() => { if (titreData.value.status === 'LOADED') { - return phaseWithAlterations(titreData.value.value.demarches, props.currentDate) + return phaseWithAlterations(titreData.value.value.titre.demarches, props.currentDate) } return [] @@ -363,24 +392,19 @@ export const PureTitre = defineComponent<Props>(props => { if (isNullOrUndefined(props.currentDemarcheSlug)) { return undefined } - const titre = titreData.value.value + const titre = titreData.value.value.titre const demarche = titre.demarches.find(({ slug }) => slug === props.currentDemarcheSlug) if (isNullOrUndefined(demarche)) { return undefined } - const firstEtapeDate = demarcheEnregistrementDemandeDateFind(demarche.etapes.map(etape => ({ ...etape, typeId: etape.etape_type_id }))) - - if (isNullOrUndefined(firstEtapeDate)) { - return undefined - } - return machineIdFind(titre.titre_type_id, demarche.demarche_type_id, demarche.id, firstEtapeDate) + return demarche.machine_id }) return () => ( <div> <LoadingElement data={titreData.value} - renderItem={titre => ( + renderItem={({ titre, machinesInfo }) => ( <div> <div class="fr-grid-row fr-grid-row--top"> <h1 style={{ maxWidth: '400px' }} class="fr-m-0"> @@ -502,6 +526,7 @@ export const PureTitre = defineComponent<Props>(props => { demarcheCreatedOrUpdated={demarcheCreatedOrUpdated} demarcheDeleted={demarcheDeleted} demarches={titre.demarches} + machinesInfo={machinesInfo} currentDemarcheSlug={props.currentDemarcheSlug} currentDate={props.currentDate} user={props.user} diff --git a/packages/ui/src/components/titre/demarche-mise-en-concurrence.stories.tsx b/packages/ui/src/components/titre/demarche-mise-en-concurrence.stories.tsx index e5e485dec..b1d810404 100644 --- a/packages/ui/src/components/titre/demarche-mise-en-concurrence.stories.tsx +++ b/packages/ui/src/components/titre/demarche-mise-en-concurrence.stories.tsx @@ -40,6 +40,7 @@ const titrePivotAvantMEC: Props['titre'] = { demarches: [ { id: idPivot, + machine_id: 'ProcedureSpecifique', demarche_type_id: DEMARCHES_TYPES_IDS.Octroi, etapes: [ { @@ -59,6 +60,7 @@ const titrePivotPendantMECEnCours: Props['titre'] = { { id: idPivot, demarche_type_id: DEMARCHES_TYPES_IDS.Octroi, + machine_id: 'ProcedureSpecifique', etapes: [ { etape_type_id: ETAPES_TYPES.demande, @@ -82,6 +84,7 @@ const titrePivotPendantMECProgrammee: Props['titre'] = { { id: idPivot, demarche_type_id: DEMARCHES_TYPES_IDS.Octroi, + machine_id: 'ProcedureSpecifique', etapes: [ { etape_type_id: ETAPES_TYPES.demande, @@ -105,6 +108,7 @@ const titrePivotPendantMECTerminee: Props['titre'] = { { id: idPivot, demarche_type_id: DEMARCHES_TYPES_IDS.Octroi, + machine_id: 'ProcedureSpecifique', etapes: [ { etape_type_id: ETAPES_TYPES.demande, @@ -128,6 +132,7 @@ const titrePivotApresMEC: Props['titre'] = { { id: idPivot, demarche_type_id: DEMARCHES_TYPES_IDS.Octroi, + machine_id: 'ProcedureSpecifique', etapes: [ { etape_type_id: ETAPES_TYPES.demande, @@ -152,6 +157,7 @@ const titreSatellite: Props['titre'] = { { id: idSatellite, demarche_type_id: DEMARCHES_TYPES_IDS.Octroi, + machine_id: 'ProcedureSpecifique', etapes: [ { etape_type_id: ETAPES_TYPES.demande, @@ -170,6 +176,7 @@ const titreSatelliteApresMEC: Props['titre'] = { { id: idSatellite, demarche_type_id: DEMARCHES_TYPES_IDS.Octroi, + machine_id: 'ProcedureSpecifique', etapes: [ { etape_type_id: ETAPES_TYPES.demande, @@ -193,6 +200,7 @@ const titreExtensionDePerimetre: Props['titre'] = { { id: idPivot, demarche_type_id: DEMARCHES_TYPES_IDS.ExtensionDePerimetre, + machine_id: 'ProcedureSpecifique', etapes: [ { etape_type_id: ETAPES_TYPES.demande, @@ -216,6 +224,7 @@ const titrePivotNonProcedureSpecifique: Props['titre'] = { { id: idPivot, demarche_type_id: DEMARCHES_TYPES_IDS.Octroi, + machine_id: 'AncienLogigrammeOctroiARM', etapes: [ { etape_type_id: ETAPES_TYPES.demande, diff --git a/packages/ui/src/components/titre/demarche-mise-en-concurrence.tsx b/packages/ui/src/components/titre/demarche-mise-en-concurrence.tsx index 7ca6aafb2..c0fc9caab 100644 --- a/packages/ui/src/components/titre/demarche-mise-en-concurrence.tsx +++ b/packages/ui/src/components/titre/demarche-mise-en-concurrence.tsx @@ -1,6 +1,6 @@ import type { ApiClient } from '@/api/api-client' import { AsyncData } from '@/api/client-rest' -import { canHaveMiseEnConcurrence, demarcheEnregistrementDemandeDateFind, DemarcheEtape, DemarcheId, demarcheIdValidator, GetDemarcheMiseEnConcurrence } from 'camino-common/src/demarche' +import { canHaveMiseEnConcurrence, DemarcheEtape, DemarcheId, demarcheIdValidator, GetDemarcheMiseEnConcurrence } from 'camino-common/src/demarche' import { computed, defineComponent, FunctionalComponent, ref } from 'vue' import { LoadingElement } from '../_ui/functional-loader' import { isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, PickDistributive } from 'camino-common/src/typescript-tools' @@ -10,14 +10,19 @@ import { ETAPE_TYPE_FOR_CONCURRENCY_DATA, ETAPES_TYPES } from 'camino-common/src import { isAdministrationRole, isSuperRole, UserNotNull } from 'camino-common/src/roles' import { watch } from 'vue' import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes' -import { CaminoMachineId, machineIdFind } from 'camino-common/src/machines' import { TitreTypeId } from 'camino-common/src/static/titresTypes' import { ETAPES_STATUTS } from 'camino-common/src/static/etapesStatuts' +import { CaminoMachineId } from 'camino-common/src/validators/machine' export type Props = { apiClient: Pick<ApiClient, 'getDemarcheMiseEnConcurrence'> titre: { titre_type_id: TitreTypeId - demarches: { id: DemarcheId; demarche_type_id: DemarcheTypeId; etapes: PickDistributive<DemarcheEtape, 'etape_type_id' | 'demarche_id_en_concurrence' | 'date' | 'etape_statut_id'>[] }[] + demarches: { + id: DemarcheId + machine_id: CaminoMachineId | null + demarche_type_id: DemarcheTypeId + etapes: PickDistributive<DemarcheEtape, 'etape_type_id' | 'demarche_id_en_concurrence' | 'date' | 'etape_statut_id'>[] + }[] } user: Pick<UserNotNull, 'role'> | null hasTitresFrom: boolean | 'LOADING' @@ -45,14 +50,8 @@ export const DemarcheMiseEnConcurrence = defineComponent<Props>(props => { conf.value = null const demarchesSansResultat = props.titre.demarches - .filter(({ demarche_type_id, etapes, id }) => { - const firstEtapeDate = demarcheEnregistrementDemandeDateFind(etapes.map(etape => ({ ...etape, typeId: etape.etape_type_id }))) - let machineId: CaminoMachineId | undefined - if (isNotNullNorUndefined(firstEtapeDate)) { - machineId = machineIdFind(props.titre.titre_type_id, demarche_type_id, id, firstEtapeDate) - } - - return machineId === 'ProcedureSpecifique' && canHaveMiseEnConcurrence(demarche_type_id, hasTitresFrom) + .filter(({ demarche_type_id, machine_id }) => { + return machine_id === 'ProcedureSpecifique' && canHaveMiseEnConcurrence(demarche_type_id, hasTitresFrom) }) .reduce<{ id: DemarcheId; hasAnf: boolean }[]>((acc, demarche) => { const hasAnf: boolean = demarche.etapes.some(etape => etape.etape_type_id === ETAPES_TYPES.avisDeMiseEnConcurrenceAuJORF) diff --git a/packages/ui/src/components/titre/phase.test.ts b/packages/ui/src/components/titre/phase.test.ts index 4c18944f2..b714450a9 100644 --- a/packages/ui/src/components/titre/phase.test.ts +++ b/packages/ui/src/components/titre/phase.test.ts @@ -17,6 +17,7 @@ test('phase en erreur', () => { demarche_date_debut: null, demarche_date_fin: null, demarche_visibilite: 'Confidentielle', + machine_id: null, ordre: 1, }, { @@ -29,6 +30,7 @@ test('phase en erreur', () => { demarche_statut_id: 'acp', demarche_date_debut: null, demarche_date_fin: null, + machine_id: null, ordre: 2, }, ] @@ -45,6 +47,7 @@ test('phase en erreur', () => { "description": null, "etapes": [], "id": "idMut", + "machine_id": null, "ordre": 1, "slug": "slug-mut", }, @@ -57,6 +60,7 @@ test('phase en erreur', () => { "description": null, "etapes": [], "id": "idDemPro", + "machine_id": null, "ordre": 2, "slug": "dem-slug-pro", }, @@ -71,6 +75,7 @@ test('phase acceptée et publiée', () => { id: demarcheIdValidator.parse('idMut'), slug: demarcheSlugValidator.parse('slug-mut'), description: null, + machine_id: null, etapes: [ { etape_type_id: 'dex', @@ -100,6 +105,7 @@ test('phase acceptée et publiée', () => { slug: demarcheSlugValidator.parse('dem-slug-pro'), description: null, demarche_visibilite: 'Confidentielle', + machine_id: null, etapes: [ { etape_type_id: 'dex', @@ -165,6 +171,7 @@ test('phase acceptée et publiée', () => { ], "events": [], "id": "idDemPro", + "machine_id": null, "ordre": 2, "slug": "dem-slug-pro", }, @@ -206,6 +213,7 @@ test('phase acceptée et publiée', () => { ], "events": [], "id": "idMut", + "machine_id": null, "ordre": 1, "slug": "slug-mut", }, diff --git a/packages/ui/src/components/titre/resultat-mise-en-concurrence.stories.tsx b/packages/ui/src/components/titre/resultat-mise-en-concurrence.stories.tsx index 8b6a955b9..59bce5b15 100644 --- a/packages/ui/src/components/titre/resultat-mise-en-concurrence.stories.tsx +++ b/packages/ui/src/components/titre/resultat-mise-en-concurrence.stories.tsx @@ -8,10 +8,12 @@ import { Entreprise, newEntrepriseId } from 'camino-common/src/entreprise' import { km2Validator } from 'camino-common/src/number' import { ETAPES_TYPES } from 'camino-common/src/static/etapesTypes' import { action } from '@storybook/addon-actions' -import { firstEtapeDateValidator, toCaminoDate } from 'camino-common/src/date' +import { toCaminoDate } from 'camino-common/src/date' import { ApiClient } from '@/api/api-client' import { tempDocumentNameValidator } from 'camino-common/src/document' import { testBlankUser } from 'camino-common/src/tests-utils' +import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes' +import { MachineInfo } from 'camino-common/src/machines' const meta: Meta = { title: 'Components/Titre/ResultatMiseEnConcurrence', @@ -80,7 +82,6 @@ const perimetreSatellite: Props['pivot']['perimetreSansSatellite'] = { surface: km2Validator.parse(5), } -const firstEtapeDate = firstEtapeDateValidator.parse('2024-10-01') const apiClient: Pick<ApiClient, 'getEtapesTypesEtapesStatuts' | 'etapeCreer' | 'uploadTempDocument' | 'getEtapeDocumentsByEtapeId'> = { getEtapeDocumentsByEtapeId: async etapeId => { getEtapeDocumentsByEtapeIdAction(etapeId) @@ -99,122 +100,143 @@ const apiClient: Pick<ApiClient, 'getEtapesTypesEtapesStatuts' | 'etapeCreer' | return tempDocumentNameValidator.parse('plop') }, } -export const Default: StoryFn = () => ( - <ResultatMiseEnConcurrence - initTab="carte" - initDate={toCaminoDate('2024-10-16')} - initDecision="acc" - entreprises={entreprises} - apiClient={{ - ...apiClient, - }} - user={{ ...testBlankUser, role: 'super' }} - pivot={{ - demarcheId, - demarcheTypeId: 'oct', - titreNom: 'Pivot', - titreSlug: titreSlugValidator.parse('titrePivotSlug'), - titreTypeId: TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - titulaireId: entrepriseId1, - perimetreSansSatellite: perimetreSatellite, - perimetreTotal: perimetre, - firstEtapeDate: firstEtapeDate, - }} - /> -) -export const Loading: StoryFn = () => ( - <ResultatMiseEnConcurrence - initTab="carte" - initDate={toCaminoDate('2024-10-16')} - entreprises={entreprises} - apiClient={{ - ...apiClient, - getEtapesTypesEtapesStatuts() { - return new Promise(() => ({})) - }, - }} - user={{ ...testBlankUser, role: 'super' }} - pivot={{ - demarcheId, - demarcheTypeId: 'oct', - titreNom: 'Pivot', - titreSlug: titreSlugValidator.parse('titrePivotSlug'), - titreTypeId: TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - titulaireId: entrepriseId1, - perimetreSansSatellite: perimetre, - perimetreTotal: perimetre, - firstEtapeDate: firstEtapeDate, - }} - /> -) +const machineInfo = MachineInfo.withMachineId(TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, DEMARCHES_TYPES_IDS.Octroi, demarcheId, 'ProcedureSpecifique') -export const WithError: StoryFn = () => ( - <ResultatMiseEnConcurrence - initTab="carte" - initDate={toCaminoDate('2024-10-16')} - entreprises={entreprises} - apiClient={{ - ...apiClient, - getEtapesTypesEtapesStatuts() { - return Promise.resolve({ message: "Message d'erreur" }) - }, - }} - user={{ ...testBlankUser, role: 'super' }} - pivot={{ - demarcheId, - demarcheTypeId: 'oct', - titreNom: 'Pivot', - titreSlug: titreSlugValidator.parse('titrePivotSlug'), - titreTypeId: TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - titulaireId: entrepriseId1, - perimetreSansSatellite: perimetre, - perimetreTotal: perimetre, - firstEtapeDate: firstEtapeDate, - }} - /> -) +if (!machineInfo.valid) { + throw new Error(machineInfo.error) +} +export const Default: StoryFn = () => { + return ( + <ResultatMiseEnConcurrence + initTab="carte" + initDate={toCaminoDate('2024-10-16')} + initDecision="acc" + entreprises={entreprises} + apiClient={{ + ...apiClient, + }} + user={{ ...testBlankUser, role: 'super' }} + pivot={{ + demarcheId, + demarcheTypeId: DEMARCHES_TYPES_IDS.Octroi, + titreNom: 'Pivot', + titreSlug: titreSlugValidator.parse('titrePivotSlug'), + titreTypeId: TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + titulaireId: entrepriseId1, + perimetreSansSatellite: perimetreSatellite, + perimetreTotal: perimetre, + machineId: 'ProcedureSpecifique', + }} + machineInfo={machineInfo.value} + /> + ) +} + +export const Loading: StoryFn = () => { + return ( + <ResultatMiseEnConcurrence + initTab="carte" + initDate={toCaminoDate('2024-10-16')} + entreprises={entreprises} + apiClient={{ + ...apiClient, + getEtapesTypesEtapesStatuts() { + return new Promise(() => ({})) + }, + }} + user={{ ...testBlankUser, role: 'super' }} + pivot={{ + demarcheId, + demarcheTypeId: 'oct', + titreNom: 'Pivot', + titreSlug: titreSlugValidator.parse('titrePivotSlug'), + titreTypeId: TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + titulaireId: entrepriseId1, + perimetreSansSatellite: perimetre, + perimetreTotal: perimetre, + machineId: 'ProcedureSpecifique', + }} + machineInfo={machineInfo.value} + /> + ) +} -export const PerimetreSansSatellite: StoryFn = () => ( - <ResultatMiseEnConcurrence - initTab="carte" - initDate={toCaminoDate('2024-10-16')} - initDecision="acc" - entreprises={entreprises} - apiClient={apiClient} - user={{ ...testBlankUser, role: 'super' }} - pivot={{ - demarcheId, - demarcheTypeId: 'oct', - titreNom: 'Pivot', - titreSlug: titreSlugValidator.parse('titrePivotSlug'), - titreTypeId: TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - titulaireId: entrepriseId1, - perimetreSansSatellite: { geojson4326_perimetre: null, surface: km2Validator.parse(0) }, - perimetreTotal: perimetre, - firstEtapeDate: firstEtapeDate, - }} - /> -) +export const WithError: StoryFn = () => { + return ( + <ResultatMiseEnConcurrence + initTab="carte" + initDate={toCaminoDate('2024-10-16')} + entreprises={entreprises} + apiClient={{ + ...apiClient, + getEtapesTypesEtapesStatuts() { + return Promise.resolve({ message: "Message d'erreur" }) + }, + }} + user={{ ...testBlankUser, role: 'super' }} + pivot={{ + demarcheId, + demarcheTypeId: 'oct', + titreNom: 'Pivot', + titreSlug: titreSlugValidator.parse('titrePivotSlug'), + titreTypeId: TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + titulaireId: entrepriseId1, + perimetreSansSatellite: perimetre, + perimetreTotal: perimetre, + machineId: 'ProcedureSpecifique', + }} + machineInfo={machineInfo.value} + /> + ) +} + +export const PerimetreSansSatellite: StoryFn = () => { + return ( + <ResultatMiseEnConcurrence + initTab="carte" + initDate={toCaminoDate('2024-10-16')} + initDecision="acc" + entreprises={entreprises} + apiClient={apiClient} + user={{ ...testBlankUser, role: 'super' }} + pivot={{ + demarcheId, + demarcheTypeId: 'oct', + titreNom: 'Pivot', + titreSlug: titreSlugValidator.parse('titrePivotSlug'), + titreTypeId: TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + titulaireId: entrepriseId1, + perimetreSansSatellite: { geojson4326_perimetre: null, surface: km2Validator.parse(0) }, + perimetreTotal: perimetre, + machineId: 'ProcedureSpecifique', + }} + machineInfo={machineInfo.value} + /> + ) +} -export const PerimetreAvecSatelliteEquivalent: StoryFn = () => ( - <ResultatMiseEnConcurrence - initTab="carte" - initDate={toCaminoDate('2024-10-16')} - initDecision="acc" - entreprises={entreprises} - apiClient={apiClient} - user={{ ...testBlankUser, role: 'super' }} - pivot={{ - demarcheId, - demarcheTypeId: 'oct', - titreNom: 'Pivot', - titreSlug: titreSlugValidator.parse('titrePivotSlug'), - titreTypeId: TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, - titulaireId: entrepriseId1, - perimetreSansSatellite: perimetre, - perimetreTotal: perimetre, - firstEtapeDate: firstEtapeDate, - }} - /> -) +export const PerimetreAvecSatelliteEquivalent: StoryFn = () => { + return ( + <ResultatMiseEnConcurrence + initTab="carte" + initDate={toCaminoDate('2024-10-16')} + initDecision="acc" + entreprises={entreprises} + apiClient={apiClient} + user={{ ...testBlankUser, role: 'super' }} + pivot={{ + demarcheId, + demarcheTypeId: 'oct', + titreNom: 'Pivot', + titreSlug: titreSlugValidator.parse('titrePivotSlug'), + titreTypeId: TITRES_TYPES_IDS.AUTORISATION_DE_RECHERCHE_METAUX, + titulaireId: entrepriseId1, + perimetreSansSatellite: perimetre, + perimetreTotal: perimetre, + machineId: 'ProcedureSpecifique', + }} + machineInfo={machineInfo.value} + /> + ) +} diff --git a/packages/ui/src/components/titre/resultat-mise-en-concurrence.tsx b/packages/ui/src/components/titre/resultat-mise-en-concurrence.tsx index 0f562fd6a..9b85dabf1 100644 --- a/packages/ui/src/components/titre/resultat-mise-en-concurrence.tsx +++ b/packages/ui/src/components/titre/resultat-mise-en-concurrence.tsx @@ -22,6 +22,7 @@ import { ETAPES_STATUTS, EtapesStatuts } from 'camino-common/src/static/etapesSt import { User } from 'camino-common/src/roles' import { ETAPE_IS_NOT_BROUILLON, EtapeDocument, TempEtapeDocument } from 'camino-common/src/etape' import { EtapeDocumentsEdit } from '../etape/etape-documents-edit' +import { MachineInfo } from 'camino-common/src/machines' export type Props = { apiClient: Pick<ApiClient, 'getEtapesTypesEtapesStatuts' | 'etapeCreer' | 'uploadTempDocument' | 'getEtapeDocumentsByEtapeId'> @@ -30,6 +31,7 @@ export type Props = { initDate?: CaminoDate initDecision?: 'acc' | 'rej' pivot: GetResultatMiseEnConcurrence + machineInfo: MachineInfo user: User } @@ -221,7 +223,7 @@ export const ResultatMiseEnConcurrence = defineComponent<Props>(props => { perimetre={perimetre.value} id="perimetre_final" titreSlug={props.pivot.titreSlug} - titreTypeId={props.pivot.titreTypeId} + machineInfo={props.machineInfo} initTab={props.initTab ?? 'carte'} /> </> @@ -255,10 +257,7 @@ export const ResultatMiseEnConcurrence = defineComponent<Props>(props => { user={props.user} sdomZoneIds={[]} tde={{ - demarcheId: props.pivot.demarcheId, - demarcheTypeId: props.pivot.demarcheTypeId, - titreTypeId: props.pivot.titreTypeId, - firstEtapeDate: props.pivot.firstEtapeDate, + machineInfo: props.machineInfo, etapeTypeId: ETAPES_TYPES.resultatMiseEnConcurrence, }} completeUpdate={onDocumentUpdate} @@ -278,4 +277,4 @@ export const ResultatMiseEnConcurrence = defineComponent<Props>(props => { }) // @ts-ignore waiting for https://github.com/vuejs/core/issues/7833 -ResultatMiseEnConcurrence.props = ['initTab', 'pivot', 'entreprises', 'apiClient', 'initDate', 'initDecision', 'user'] +ResultatMiseEnConcurrence.props = ['initTab', 'pivot', 'machineInfo', 'entreprises', 'apiClient', 'initDate', 'initDecision', 'user'] diff --git a/packages/ui/src/components/titre/titre-demarche.tsx b/packages/ui/src/components/titre/titre-demarche.tsx index ef73ad7e5..50c6bdd1c 100644 --- a/packages/ui/src/components/titre/titre-demarche.tsx +++ b/packages/ui/src/components/titre/titre-demarche.tsx @@ -1,6 +1,6 @@ import { FunctionalComponent, computed, defineComponent, ref } from 'vue' import { getMostRecentValuePropFromEtapeFondamentaleValide, TitreGet, TitreGetDemarche } from 'camino-common/src/titres' -import { demarcheEnregistrementDemandeDateFind, DemarcheEtapeFondamentale, DemarcheSlug, getDemarcheContenu } from 'camino-common/src/demarche' +import { DemarcheEtapeFondamentale, DemarcheId, DemarcheSlug, getDemarcheContenu } from 'camino-common/src/demarche' import { DemarchesTypes, isTravaux } from 'camino-common/src/static/demarchesTypes' import { DemarcheStatut } from '@/components/_common/demarche-statut' import { isNonEmptyArray, isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty, isNullOrUndefined, onlyUnique } from 'camino-common/src/typescript-tools' @@ -25,14 +25,15 @@ import { isDemarcheStatutNonStatue, isDemarcheStatutNonValide } from 'camino-com import { capitalize } from 'camino-common/src/strings' import { CaminoRouter } from '@/typings/vue-router' import { Alert } from '../_ui/alert' -import { CaminoDate, firstEtapeDateValidator } from 'camino-common/src/date' -import { machineIdFind } from 'camino-common/src/machines' +import { CaminoDate } from 'camino-common/src/date' import { fr } from '@codegouvfr/react-dsfr' import { DemarcheVisibilite } from '../_common/demarche-visibilite' +import { MachineInfo } from 'camino-common/src/machines' type Props = { titre: Pick<TitreGet, 'id' | 'slug' | 'titre_type_id' | 'titre_statut_id' | 'nom' | 'titre_visibilite'> demarches: TitreGetDemarche[] + machinesInfo: Record<DemarcheId, MachineInfo> currentDemarcheSlug: DemarcheSlug currentDate: CaminoDate apiClient: Pick<ApiClient, 'deleteEtape' | 'deposeEtape' | 'getTitresWithPerimetreForCarte' | 'createDemarche' | 'updateDemarche' | 'deleteDemarche' | 'getEtapesTypesEtapesStatuts' | 'etapeCreer'> @@ -170,7 +171,7 @@ export const TitreDemarche = defineComponent<Props>(props => { icon="fr-icon-delete-bin-line" class="fr-ml-2w" buttonType="secondary" - title={`Supprimer la démarche ${isNotNullNorUndefinedNorEmpty(orderedEtapes.value) ? (machineIdFind(props.titre.titre_type_id, demarche.value.demarche_type_id, demarche.value.id, demarcheEnregistrementDemandeDateFind(orderedEtapes.value.map(etape => ({ date: etape.date, typeId: etape.etape_type_id }))) ?? firstEtapeDateValidator.parse(orderedEtapes.value)) ?? 'TDE') : 'vide'}`} + title={`Supprimer la démarche ${isNotNullNorUndefined(demarche.value.machine_id) ? demarche.value.machine_id : 'TDE'}`} onClick={openDeleteDemarchePopup} /> ) : null} @@ -221,7 +222,7 @@ export const TitreDemarche = defineComponent<Props>(props => { <DsfrPerimetre class="fr-pt-3w" titreSlug={props.titre.slug} - titreTypeId={props.titre.titre_type_id} + machineInfo={props.machinesInfo[demarche.value.id]} id={props.currentDemarcheSlug} apiClient={props.apiClient} calculateNeighbours={true} @@ -235,7 +236,7 @@ export const TitreDemarche = defineComponent<Props>(props => { <div class="fr-mt-3w" style={{ display: 'flex', alignContent: 'center' }}> <h3 class="fr-mb-0">Étapes</h3> <div style={{ marginLeft: 'auto' }}> - {canPublishResultatMiseEnConcurrence(props.user, props.titre.titre_type_id, demarche.value.demarche_type_id, demarche.value.etapes, demarche.value.id).valid ? ( + {canPublishResultatMiseEnConcurrence(props.user, props.machinesInfo[demarche.value.id], demarche.value.etapes).valid ? ( <DsfrLink buttonType="primary" class="fr-mr-2w" @@ -247,11 +248,7 @@ export const TitreDemarche = defineComponent<Props>(props => { ) : null} {canCreateEtapeByDemarche(props.user, props.titre.titre_type_id, demarche.value.demarche_type_id, administrations.value, props.titre.titre_statut_id) ? ( <DsfrLink - buttonType={ - canPublishResultatMiseEnConcurrence(props.user, props.titre.titre_type_id, demarche.value.demarche_type_id, demarche.value.etapes, demarche.value.id).valid - ? 'secondary' - : 'primary' - } + buttonType={canPublishResultatMiseEnConcurrence(props.user, props.machinesInfo[demarche.value.id], demarche.value.etapes).valid ? 'secondary' : 'primary'} icon={null} disabled={false} title="Ajouter une étape" @@ -287,6 +284,7 @@ export const TitreDemarche = defineComponent<Props>(props => { sdom_zones: perimetre.value?.sdom_zones ?? [], communes: perimetre.value?.communes?.map(({ id }) => id) ?? [], etapes: demarche.value.etapes, + machineInfo: props.machinesInfo[demarche.value.id], }} apiClient={props.apiClient} currentDate={props.currentDate} @@ -338,7 +336,20 @@ export const TitreDemarche = defineComponent<Props>(props => { }) // @ts-ignore waiting for https://github.com/vuejs/core/issues/7833 -TitreDemarche.props = ['titre', 'demarches', 'currentDemarcheSlug', 'currentDate', 'apiClient', 'user', 'entreprises', 'router', 'initTab', 'demarcheCreatedOrUpdated', 'demarcheDeleted'] +TitreDemarche.props = [ + 'titre', + 'demarches', + 'machinesInfo', + 'currentDemarcheSlug', + 'currentDate', + 'apiClient', + 'user', + 'entreprises', + 'router', + 'initTab', + 'demarcheCreatedOrUpdated', + 'demarcheDeleted', +] const DisplayLocalisation: FunctionalComponent<Pick<DemarcheEtapeFondamentale['fondamentale'], 'perimetre'>> = props => { if (isNullOrUndefined(props.perimetre)) { -- GitLab