diff --git a/packages/api/src/business/rules-demarches/prm/oct.machine.test.ts b/packages/api/src/business/rules-demarches/prm/oct.machine.test.ts index 58d4f9a3b7bf4cb50c1eec407a0a46a417970f39..bca8694a82e886c2136188d32ce51c96e2b12d58 100644 --- a/packages/api/src/business/rules-demarches/prm/oct.machine.test.ts +++ b/packages/api/src/business/rules-demarches/prm/oct.machine.test.ts @@ -7,9 +7,9 @@ import { km2Validator } from 'camino-common/src/number' import { TITRES_TYPES_IDS } from 'camino-common/src/static/titresTypes' import { DEMARCHES_TYPES_IDS } from 'camino-common/src/static/demarchesTypes' -describe('vérifie l’arbre d’octroi de PRM', () => { +describe("vérifie l'arbre d'octroi de PRM", () => { const prmOctMachine = new PrmOctMachine(TITRES_TYPES_IDS.PERMIS_EXCLUSIF_DE_RECHERCHES_METAUX, DEMARCHES_TYPES_IDS.Octroi) - test('peut créer une demande d’octroi de PRM complète en Métropole', () => { + test("peut créer une demande d'octroi de PRM complète en Métropole", () => { const { tree } = setDateAndOrderAndInterpretMachine(prmOctMachine, '2022-07-01', [ ETES.demande.FAIT, ETES.enregistrementDeLaDemande.FAIT, @@ -74,7 +74,7 @@ describe('vérifie l’arbre d’octroi de PRM', () => { `) }) - test('peut créer une demande d’octroi de PRM en Guyane', () => { + test("peut créer une demande d'octroi de PRM en Guyane", () => { const etapes = [ { ...ETES.demande.FAIT, paysId: PAYS_IDS['Département de la Guyane'], surface: km2Validator.parse(200) }, ETES.enregistrementDeLaDemande.FAIT, @@ -107,7 +107,7 @@ describe('vérifie l’arbre d’octroi de PRM', () => { `) }) - test('peut créer une demande d’octroi de PRM en Guyane sans avis du maire', () => { + test("peut créer une demande d'octroi de PRM en Guyane sans avis du maire", () => { const etapes = [ { ...ETES.demande.FAIT, paysId: PAYS_IDS['Département de la Guyane'], surface: km2Validator.parse(14) }, ETES.enregistrementDeLaDemande.FAIT, @@ -139,7 +139,7 @@ describe('vérifie l’arbre d’octroi de PRM', () => { `) }) - test('peut créer une demande d’octroi de PRM en Outre mer (hors Guyane)', () => { + test("peut créer une demande d'octroi de PRM en Outre mer (hors Guyane)", () => { const etapes = [ { ...ETES.demande.FAIT, paysId: PAYS_IDS['Wallis-et-Futuna'] }, ETES.enregistrementDeLaDemande.FAIT, @@ -170,7 +170,7 @@ describe('vérifie l’arbre d’octroi de PRM', () => { `) }) - test('ne peut pas faire l’avis de la DREAL si la saisine des services a été faite dans les 30 jours', () => { + test("ne peut pas faire l'avis de la DREAL si la saisine des services a été faite dans les 30 jours", () => { const etapes = [ { ...ETES.demande.FAIT, paysId: PAYS_IDS['République Française'] }, ETES.enregistrementDeLaDemande.FAIT, @@ -200,7 +200,7 @@ describe('vérifie l’arbre d’octroi de PRM', () => { ) }) - test('ne peut pas ouvrir la consultation du public si la mise en concurrence n’est pas terminée', () => { + test("ne peut pas ouvrir la consultation du public si la mise en concurrence n'est pas terminée", () => { const etapes = [ { ...ETES.demande.FAIT, paysId: PAYS_IDS['République Française'] }, ETES.enregistrementDeLaDemande.FAIT, 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 90268ff2821b2ff838c0ca1588f20de8acd6d0d0..16e21079bfc5e49926cebe204e6d4b0d38fd0fbe 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 @@ -15,6 +15,7 @@ import { ProcedureSpecifiqueMachine } from '../rules-demarches/procedure-specifi 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' console.warn = vi.fn() @@ -247,7 +248,7 @@ describe('titreDemarcheUpdatedEtatValidate', () => { { id: newEtapeId('2'), typeId: 'men', - date: toCaminoDate('2022-05-04'), + date: toCaminoDate('2022-05-05'), statutId: 'fai', isBrouillon: ETAPE_IS_NOT_BROUILLON, communes: null, @@ -261,7 +262,7 @@ describe('titreDemarcheUpdatedEtatValidate', () => { ] ) - expect(valid.valid).toBe(true) + expect(valid.valid, JSON.stringify(valid)).toBe(true) }) test('l’ajout d’une étape d’une démarche historique est valide', () => { @@ -671,6 +672,140 @@ describe('titreDemarcheUpdatedEtatValidate', () => { }) describe('getPossiblesEtapesTypes', () => { + test('peut déplacer le Rapport et avis de la DREAL avant la Consultation du public pour les Octrois de Permis exclusif de recherches ', () => { + const apdId = newEtapeId('apiId') + const etapes: TitreEtapeForMachine[] = [ + { + typeId: ETAPES_TYPES.rapportEtAvisDeLaDREAL, + date: toCaminoDate('2024-05-29'), + isBrouillon: ETAPE_IS_NOT_BROUILLON, + id: apdId, + ordre: 8, + statutId: 'fav', + communes: [], + demarcheIdsConsentement: [], + }, + { + typeId: ETAPES_TYPES.avisDesServicesEtCommissionsConsultatives, + date: toCaminoDate('2023-12-22'), + isBrouillon: ETAPE_IS_NOT_BROUILLON, + id: newEtapeId('avisDesServicesEtCommissionsConsultatives'), + ordre: 6, + statutId: 'fai', + communes: [], + demarcheIdsConsentement: [], + }, + { + typeId: ETAPES_TYPES.consultationDuPublic, + date: toCaminoDate('2024-05-28'), + isBrouillon: ETAPE_IS_NOT_BROUILLON, + id: newEtapeId('ppuID'), + ordre: 7, + statutId: 'ter', + communes: [], + demarcheIdsConsentement: [], + }, + { + typeId: ETAPES_TYPES.demande, + date: toCaminoDate('2023-02-28'), + isBrouillon: ETAPE_IS_NOT_BROUILLON, + id: newEtapeId('demandeId'), + ordre: 1, + statutId: 'fai', + communes: [{ id: toCommuneId('64012') }], + demarcheIdsConsentement: [], + }, + { + typeId: ETAPES_TYPES.avisDeMiseEnConcurrenceAuJORF, + date: toCaminoDate('2023-09-01'), + isBrouillon: ETAPE_IS_NOT_BROUILLON, + id: newEtapeId('anf'), + ordre: 5, + statutId: 'ter', + communes: [{ id: toCommuneId('64012') }], + demarcheIdsConsentement: [], + }, + { + typeId: ETAPES_TYPES.enregistrementDeLaDemande, + date: toCaminoDate('2023-05-03'), + isBrouillon: ETAPE_IS_NOT_BROUILLON, + id: newEtapeId('men'), + ordre: 2, + statutId: 'fai', + communes: [], + demarcheIdsConsentement: [], + }, + { + typeId: ETAPES_TYPES.saisineDuPrefet, + date: toCaminoDate('2023-05-03'), + isBrouillon: ETAPE_IS_NOT_BROUILLON, + id: newEtapeId('spp'), + ordre: 3, + statutId: 'fai', + communes: [], + demarcheIdsConsentement: [], + }, + { + typeId: ETAPES_TYPES.recevabiliteDeLaDemande, + date: toCaminoDate('2023-06-23'), + isBrouillon: ETAPE_IS_NOT_BROUILLON, + id: newEtapeId('mcr'), + ordre: 4, + statutId: 'fav', + communes: [], + demarcheIdsConsentement: [], + }, + ] + + 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, + ETAPES_TYPES.rapportEtAvisDeLaDREAL, + apdId, + toCaminoDate('2024-05-22'), + etapes + ) + ).toMatchInlineSnapshot(` + { + "apd": { + "etapeStatutIds": [ + "fav", + "def", + "fre", + "dre", + ], + "mainStep": true, + }, + "mec": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "mif": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "mod": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + "rif": { + "etapeStatutIds": [ + "fai", + ], + "mainStep": false, + }, + } + `) + }) + 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(` { @@ -743,7 +878,7 @@ describe('getPossiblesEtapesTypes', () => { hasTitreFrom: 'non-applicable', isBrouillon: ETAPE_IS_NOT_BROUILLON, ordre: 10, - date: toCaminoDate('2019-12-04'), + date: toCaminoDate('2019-12-06'), dateFin: null, dateDebut: null, duree: null, @@ -760,7 +895,7 @@ describe('getPossiblesEtapesTypes', () => { hasTitreFrom: 'non-applicable', isBrouillon: ETAPE_IS_NOT_BROUILLON, ordre: 14, - date: toCaminoDate('2020-05-22'), + date: toCaminoDate('2020-05-21'), dateFin: null, dateDebut: null, duree: null, @@ -777,7 +912,7 @@ describe('getPossiblesEtapesTypes', () => { hasTitreFrom: 'non-applicable', isBrouillon: ETAPE_IS_NOT_BROUILLON, ordre: 8, - date: toCaminoDate('2019-12-04'), + date: toCaminoDate('2019-12-05'), dateFin: null, dateDebut: null, duree: null, @@ -862,7 +997,7 @@ describe('getPossiblesEtapesTypes', () => { hasTitreFrom: 'non-applicable', isBrouillon: ETAPE_IS_NOT_BROUILLON, ordre: 6, - date: toCaminoDate('2019-12-04'), + date: toCaminoDate('2019-12-03'), dateFin: null, dateDebut: null, duree: null, @@ -972,15 +1107,10 @@ describe('getPossiblesEtapesTypes', () => { `) }) - test('modifie une étape existante à la même date devrait permettre de recréer la même étape', () => { - for (const etape of etapes) { - const etapesTypesPossibles = getPossiblesEtapesTypes(machine, 'arm', 'oct', undefined, etape.id, etape.date, etapes) - if (Object.keys(etapesTypesPossibles).length === 0) { - console.error(`pas d'étapes possibles à l'étape ${JSON.stringify(etape)}. Devrait contenir AU MOINS la même étape`) - } - expect(Object.keys(etapesTypesPossibles).length).toBeGreaterThan(0) - expect(etapesTypesPossibles[etape.typeId]).toHaveProperty('etapeStatutIds') - } + 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) + 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', () => { @@ -998,7 +1128,7 @@ describe('getPossiblesEtapesTypes', () => { test('ajoute une nouvelle étape en plein milieu', () => { const tested = getPossiblesEtapesTypes(machine, 'arm', 'oct', undefined, undefined, toCaminoDate('2019-12-04'), etapes) - expect(Object.keys(tested).toSorted()).toStrictEqual(['exp', 'mod']) + expect(Object.keys(tested).toSorted()).toStrictEqual(['mca', 'mim', 'mod']) }) test('peut faire une dae, une rde et pfd AVANT la mfr', () => { 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 ea3c25c5891db4b20b73e70bffa6f8006dde92bb..df69a3fec9286bb1bb684e6682509d495f90df80 100644 --- a/packages/api/src/business/validations/titre-demarche-etat-validate.ts +++ b/packages/api/src/business/validations/titre-demarche-etat-validate.ts @@ -190,21 +190,15 @@ export const getPossiblesEtapesTypes = ( } const etapesTypesPossibleACetteDateOuALaPlaceDeLEtape = (machine: CaminoMachines, etapes: TitreEtapeForMachine[], titreEtapeId: string | null, date: CaminoDate): EtapeTypeEtapeStatutWithMainStep => { - const sortedEtapes = titreEtapesSortAscByOrdre(etapes) + const sortedEtapes = titreEtapesSortAscByOrdre(etapes).filter(etape => etape.id !== titreEtapeId) const etapesAvant: Etape[] = [] const etapesApres: Etape[] = [] - if (isNotNullNorUndefined(titreEtapeId)) { - const index = sortedEtapes.findIndex(etape => etape.id === titreEtapeId) - etapesAvant.push(...toMachineEtapes(sortedEtapes.slice(0, index))) - etapesApres.push(...toMachineEtapes(sortedEtapes.slice(index + 1))) - } else { - // TODO 2022-07-12: Il faudrait mieux gérer les étapes à la même date que l'étape qu'on veut rajouter - // elles ne sont ni avant, ni après, mais potentiellement au milieu de toutes ces étapes - // - etapesAvant.push(...toMachineEtapes(sortedEtapes.filter(etape => etape.date <= date))) - etapesApres.push(...toMachineEtapes(sortedEtapes.slice(etapesAvant.length))) - } + // TODO 2022-07-12: Il faudrait mieux gérer les étapes à la même date que l'étape qu'on veut rajouter + // elles ne sont ni avant, ni après, mais potentiellement au milieu de toutes ces étapes + // UPDATE 2025-03-31: il n'y en a pas en prod + etapesAvant.push(...toMachineEtapes(sortedEtapes.filter(etape => etape.date <= date))) + etapesApres.push(...toMachineEtapes(sortedEtapes.slice(etapesAvant.length))) const etapesPossiblesRaw = machine.possibleNextEtapes(etapesAvant, date) const etapesPossibles = []