Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Impossible d'abandonner un projet achevé #2670

Merged
merged 7 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const PorteurProjetActions = ({
familleId: project.familleId,
numeroCRE: project.numeroCRE,
}).formatter();
const peutDemanderAbandon = !abandonEnCours && !hasAttestationConformité;

return (
<div className="flex flex-col gap-3">
Expand Down Expand Up @@ -109,7 +110,7 @@ const PorteurProjetActions = ({
<span>Demander un changement de représentant légal</span>
</DropdownMenuSecondaryButton.DropdownItem>
)}
{!abandonEnCours && (
{peutDemanderAbandon && (
<>
<DropdownMenuSecondaryButton.DropdownItem
href={Routes.Abandon.demander(identifiantProjet)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ export type AnnulerRejetOptions = {
dateAnnulation: DateTime.ValueType;
identifiantUtilisateur: IdentifiantUtilisateur.ValueType;
identifiantProjet: IdentifiantProjet.ValueType;
estAchevé: boolean;
};

export async function annulerRejet(
this: AbandonAggregate,
{ dateAnnulation, identifiantUtilisateur, identifiantProjet }: AnnulerRejetOptions,
{ dateAnnulation, identifiantUtilisateur, identifiantProjet, estAchevé }: AnnulerRejetOptions,
) {
this.statut.vérifierQueLeChangementDeStatutEstPossibleEn(StatutAbandon.demandé);

Expand All @@ -35,6 +36,7 @@ export async function annulerRejet(
raison: this.demande.raison,
identifiantUtilisateur: this.demande.demandéPar,
pièceJustificative: this.demande.pièceJustificative,
estAchevé,
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { IdentifiantUtilisateur } from '@potentiel-domain/utilisateur';
import { LoadAggregate } from '@potentiel-domain/core';

import { loadAbandonFactory } from '../abandon.aggregate';
import { loadAchèvementFactory } from '../../achèvement/achèvement.aggregate';

export type AnnulerRejetAbandonCommand = Message<
'Lauréat.Abandon.Command.AnnulerRejetAbandon',
Expand All @@ -17,17 +18,21 @@ export type AnnulerRejetAbandonCommand = Message<

export const registerAnnulerRejetAbandonCommand = (loadAggregate: LoadAggregate) => {
const loadAbandon = loadAbandonFactory(loadAggregate);
const loadAchèvement = loadAchèvementFactory(loadAggregate);

const handler: MessageHandler<AnnulerRejetAbandonCommand> = async ({
dateAnnulation,
identifiantUtilisateur,
identifiantProjet,
}) => {
const abandon = await loadAbandon(identifiantProjet);
const achèvement = await loadAchèvement(identifiantProjet, false);

await abandon.annulerRejet({
dateAnnulation,
identifiantProjet,
identifiantUtilisateur,
estAchevé: achèvement.estAchevé(),
});
};
mediator.register('Lauréat.Abandon.Command.AnnulerRejetAbandon', handler);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export type DemanderOptions = {
identifiantProjet: IdentifiantProjet.ValueType;
pièceJustificative: DocumentProjet.ValueType;
raison: string;
estAchevé: boolean;
};

export async function demander(
Expand All @@ -56,9 +57,13 @@ export async function demander(
identifiantProjet,
pièceJustificative,
raison,
estAchevé,
}: DemanderOptions,
) {
this.statut.vérifierQueLeChangementDeStatutEstPossibleEn(StatutAbandon.demandé);
if (estAchevé) {
throw new ProjetAchevéError(identifiantProjet);
}

if (!pièceJustificative) {
throw new PièceJustificativeObligatoireError();
Expand Down Expand Up @@ -114,3 +119,9 @@ class PièceJustificativeObligatoireError extends InvalidOperationError {
super('La pièce justificative est obligatoire');
}
}

class ProjetAchevéError extends InvalidOperationError {
constructor(public identifiantProjet: IdentifiantProjet.ValueType) {
super("Impossible de demander l'abandon d'un projet achevé");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { DocumentProjet } from '@potentiel-domain/document';
import { LoadAggregate } from '@potentiel-domain/core';

import { loadAbandonFactory } from '../abandon.aggregate';
import { loadAchèvementFactory } from '../../achèvement/achèvement.aggregate';

export type DemanderAbandonCommand = Message<
'Lauréat.Abandon.Command.DemanderAbandon',
Expand All @@ -20,6 +21,8 @@ export type DemanderAbandonCommand = Message<

export const registerDemanderAbandonCommand = (loadAggregate: LoadAggregate) => {
const loadAbandon = loadAbandonFactory(loadAggregate);
const loadAchèvement = loadAchèvementFactory(loadAggregate);

const handler: MessageHandler<DemanderAbandonCommand> = async ({
identifiantProjet,
pièceJustificative,
Expand All @@ -28,13 +31,15 @@ export const registerDemanderAbandonCommand = (loadAggregate: LoadAggregate) =>
dateDemande,
}) => {
const abandon = await loadAbandon(identifiantProjet, false);
const achèvement = await loadAchèvement(identifiantProjet, false);

await abandon.demander({
identifiantProjet,
pièceJustificative,
raison,
identifiantUtilisateur,
dateDemande,
estAchevé: achèvement.estAchevé(),
});
};
mediator.register('Lauréat.Abandon.Command.DemanderAbandon', handler);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Fonctionnalité: Demander l'abandon d'un projet lauréat
Quand le porteur demande l'abandon pour le projet lauréat
Alors le porteur devrait être informé que "L'abandon a déjà été accordé"

@NotImplemented
Scénario: Impossible de demander l'abandon d'un projet si celui-ci est achevé (car l'attestation de conformité et la preuve de transmission au co-contractant ont été transmise)

Scénario: Impossible de demander l'abandon d'un projet achevé
Etant donné une attestation de conformité transmise pour le projet lauréat
Quand le porteur demande l'abandon pour le projet lauréat
Alors le porteur devrait être informé que "Impossible de demander l'abandon d'un projet achevé"
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Fonctionnalité: Modifier une attestation de conformité
Etant donné le projet lauréat "Centrale PV"

Scénario: Un porteur modifie une attestation de conformité
Et une attestation de conformité transmise pour le projet "Centrale PV"
Et une attestation de conformité transmise pour le projet lauréat
Quand l'admin modifie l'attestation de conformité pour le projet "Centrale PV" avec :
| format attestation | application/pdf |
| contenu attestation | le nouveau contenu de l'attestation |
Expand All @@ -23,7 +23,7 @@ Fonctionnalité: Modifier une attestation de conformité
| mis à jour par | admin |

Scénario: Impossible de modifier une attestation de conformité si la date de transmission au co-contractant est dans le futur
Et une attestation de conformité transmise pour le projet "Centrale PV"
Et une attestation de conformité transmise pour le projet lauréat
Quand l'admin modifie l'attestation de conformité pour le projet "Centrale PV" avec :
| date transmission au co-contractant | 2040-01-01 |
Alors le porteur devrait être informé que "la date de transmission au co-contractant ne peut pas être une date future"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import { PotentielWorld } from '../../../../../potentiel.world';
import { convertStringToReadableStream } from '../../../../../helpers/convertStringToReadable';

EtantDonné(
'une attestation de conformité transmise pour le projet {string}',
async function (this: PotentielWorld, nomProjet: string) {
const { identifiantProjet } = this.lauréatWorld.rechercherLauréatFixture(nomProjet);
'une attestation de conformité transmise pour le projet lauréat',
async function (this: PotentielWorld) {
const { identifiantProjet } = this.lauréatWorld;

const attestationValue = {
content: convertStringToReadableStream('contenu par défaut'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ Fonctionnalité: Transmettre une attestation de conformité
Alors le porteur devrait être informé que "la date de transmission au co-contractant ne peut pas être une date future"

Scénario: Impossible de transmettre une attestation de conformité si le projet a déjà une attestation de conformité
Et une attestation de conformité transmise pour le projet "Du boulodrome de Marseille"
Et une attestation de conformité transmise pour le projet lauréat
Quand le porteur transmet une attestation de conformité pour le projet lauréat "Du boulodrome de Marseille" avec :
| format attestation | application/pdf |
| contenu attestation | le contenu de l'attestation |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,6 @@ Fonctionnalité: Demander le changement de l'actionnaire d'un projet lauréat
Alors le porteur devrait être informé que "Impossible de demander le changement d'actionnaire car une demande d'abandon est en cours pour le projet"

Scénario: Impossible de demander le changement de l'actionnaire d'un projet achevé
Etant donné une attestation de conformité transmise pour le projet "Du boulodrome de Marseille"
Etant donné une attestation de conformité transmise pour le projet lauréat
Quand le porteur demande le changement de l'actionnaire pour le projet lauréat
Alors le porteur devrait être informé que "Impossible de demander le changement d'actionnaire pour un projet achevé"
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Fonctionnalité: Enregistrer un changement d'actionnaire d'un projet lauréat
Alors le porteur devrait être informé que "Impossible de demander le changement d'actionnaire car une demande d'abandon est en cours pour le projet"

Scénario: Impossible pour le porteur de modifier l'actionnaire d'un projet achevé
Etant donné une attestation de conformité transmise pour le projet "Du boulodrome de Marseille"
Etant donné une attestation de conformité transmise pour le projet lauréat
Quand le porteur enregistre un changement d'actionnaire pour le projet lauréat
Alors le porteur devrait être informé que "Impossible de demander le changement d'actionnaire pour un projet achevé"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Fonctionnalité: Modifier l'actionnaire d'un projet lauréat
| la DREAL associée au projet |

Scénario: Modifier l'actionnaire d'un projet lauréat abandonné par une dreal ou un admin
Etant donné une attestation de conformité transmise pour le projet "Du boulodrome de Marseille"
Etant donné une attestation de conformité transmise pour le projet lauréat
Quand <l'utilisateur autorisé> modifie l'actionnaire pour le projet lauréat
Alors l'actionnaire du projet lauréat devrait être mis à jour
Et un email a été envoyé au porteur avec :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ Fonctionnalité: Modifier des garanties financières actuelles
Alors l'utilisateur devrait être informé que "Il n'y a aucunes garanties financières actuelles pour ce projet"

Scénario: Impossible de modifier des garanties financières actuelles si les garanties financières du projet sont levées
Etant donné une attestation de conformité transmise pour le projet "Du boulodrome de Marseille"
Etant donné une attestation de conformité transmise pour le projet lauréat
Et des garanties financières actuelles pour le projet "Du boulodrome de Marseille"
Et une demande de mainlevée de garanties financières accordée pour le projet "Du boulodrome de Marseille" achevé
Quand un admin modifie les garanties financières actuelles pour le projet "Du boulodrome de Marseille" avec :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Fonctionnalité: Échoir les garanties financières actuelles d'un projet
Etant donné des garanties financières actuelles pour le projet "Du boulodrome de Marseille" avec :
| type GF | avec-date-échéance |
| date d'échéance | 2024-07-17 |
Et une attestation de conformité transmise pour le projet "Du boulodrome de Marseille"
Et une attestation de conformité transmise pour le projet lauréat
Quand un admin échoie les garanties financières actuelles pour le projet "Du boulodrome de Marseille" avec :
| date d'échéance | 2024-07-17 |
| date à vérifier | 2024-07-18 |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ Fonctionnalité: Soumettre de nouvelles garanties financières
Alors l'utilisateur devrait être informé que "Il y a déjà des garanties financières en attente de validation pour ce projet"

Scénario: Impossible de soumettre un dépôt de garanties financières si une demande de mainlevée a été demandée
Etant donné une attestation de conformité transmise pour le projet "Du boulodrome de Marseille"
Etant donné une attestation de conformité transmise pour le projet lauréat
Et des garanties financières actuelles pour le projet "Du boulodrome de Marseille"
Et une demande de mainlevée de garanties financières pour le projet "Du boulodrome de Marseille" avec :
| motif | projet-achevé |
Expand All @@ -100,15 +100,15 @@ Fonctionnalité: Soumettre de nouvelles garanties financières
Alors l'utilisateur devrait être informé que "Vous ne pouvez pas déposer de nouvelles garanties financières car vous avez une demande de mainlevée de garanties financières en cours"

Scénario: Impossible de soumettre un dépôt de garanties financières si une demande de mainlevée est en instruction
Etant donné une attestation de conformité transmise pour le projet "Du boulodrome de Marseille"
Etant donné une attestation de conformité transmise pour le projet lauréat
Et des garanties financières actuelles pour le projet "Du boulodrome de Marseille"
Et une demande de mainlevée de garanties financières en instruction pour le projet "Du boulodrome de Marseille"
Quand un porteur soumet un dépôt de garanties financières pour le projet "Du boulodrome de Marseille" avec :
| type GF | consignation |
Alors l'utilisateur devrait être informé que "Vous ne pouvez pas déposer de nouvelles garanties financières car vous avez une mainlevée de garanties financières en cours d'instruction"

Scénario: Impossible de soumettre un dépôt de garanties financières si les garanties financières du projet sont levées
Etant donné une attestation de conformité transmise pour le projet "Du boulodrome de Marseille"
Etant donné une attestation de conformité transmise pour le projet lauréat
Et des garanties financières actuelles pour le projet "Du boulodrome de Marseille"
Et une demande de mainlevée de garanties financières accordée pour le projet "Du boulodrome de Marseille" achevé
Quand un porteur soumet un dépôt de garanties financières pour le projet "Du boulodrome de Marseille" avec :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Fonctionnalité: Accorder une demande de mainlevée des garanties financières
| contenu fichier réponse | contenu du fichier |

Scénario: Un utilisateur Dreal accorde une demande de mainlevée pour un projet achevé
Etant donné une attestation de conformité transmise pour le projet "Du boulodrome de Marseille"
Etant donné une attestation de conformité transmise pour le projet lauréat
Et des garanties financières actuelles pour le projet "Du boulodrome de Marseille"
Et une demande de mainlevée de garanties financières pour le projet "Du boulodrome de Marseille" avec :
| motif | projet-achevé |
Expand All @@ -42,21 +42,21 @@ Fonctionnalité: Accorder une demande de mainlevée des garanties financières
| contenu fichier réponse | contenu du fichier |

Scénario: Impossible d'accorder une demande de mainlevée si le projet n'a pas de demande de mainlevée
Etant donné une attestation de conformité transmise pour le projet "Du boulodrome de Marseille"
Etant donné une attestation de conformité transmise pour le projet lauréat
Et des garanties financières actuelles pour le projet "Du boulodrome de Marseille"
Quand un utilisateur Dreal accorde la demande de mainlevée des garanties financières du projet "Du boulodrome de Marseille"
Alors l'utilisateur devrait être informé que "Il n'y a pas de demande de mainlevée de garanties financières en cours pour ce projet"

Scénario: Impossible d'accorder une demande de mainlevée si le projet a déjà une demande de mainlevée accordée
Etant donné des garanties financières actuelles pour le projet "Du boulodrome de Marseille"
Et une attestation de conformité transmise pour le projet "Du boulodrome de Marseille"
Et une attestation de conformité transmise pour le projet lauréat
Et une demande de mainlevée de garanties financières accordée pour le projet "Du boulodrome de Marseille" achevé
Quand un utilisateur Dreal accorde la demande de mainlevée des garanties financières du projet "Du boulodrome de Marseille"
Alors le porteur devrait être informé que "Il y a déjà une demande de mainlevée accordée pour ce projet"

Scénario: Impossible d'accorder une demande de mainlevée si le projet a déjà une demande de mainlevée rejetée et aucune en cours
Etant donné des garanties financières actuelles pour le projet "Du boulodrome de Marseille"
Et une attestation de conformité transmise pour le projet "Du boulodrome de Marseille"
Et une attestation de conformité transmise pour le projet lauréat
Et une demande de mainlevée de garanties financières rejetée pour le projet "Du boulodrome de Marseille" achevé
Quand un utilisateur Dreal accorde la demande de mainlevée des garanties financières du projet "Du boulodrome de Marseille"
Alors le porteur devrait être informé que "La dernière demande de mainlevée pour ce projet a été rejetée, aucune n'est en cours"
Loading