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

✨ Envoi de notifications lors du changement de statut d'une demande de recours #2234

Merged
merged 3 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
21 changes: 20 additions & 1 deletion packages/applications/bootstrap/src/setupEliminé.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import {
RecoursAdapter,
} from '@potentiel-infrastructure/domain-adapters';
import { RecoursProjector, ÉliminéProjector } from '@potentiel-applications/projectors';
import { SendEmail, ÉliminéNotification } from '@potentiel-applications/notifications';
import {
RecoursNotification,
SendEmail,
ÉliminéNotification,
} from '@potentiel-applications/notifications';
import { AttestationSaga } from '@potentiel-applications/document-builder';

type SetupÉliminéDependenices = {
Expand All @@ -31,6 +35,7 @@ export const setupEliminé = async ({ sendEmail }: SetupÉliminéDependenices) =
ÉliminéNotification.register({ sendEmail });

RecoursProjector.register();
RecoursNotification.register({ sendEmail });

const unsubscribeRecoursProjector = await subscribe<RecoursProjector.SubscriptionEvent>({
name: 'projector',
Expand All @@ -50,6 +55,18 @@ export const setupEliminé = async ({ sendEmail }: SetupÉliminéDependenices) =
streamCategory: 'recours',
});

const unsubscribeRecoursNotification = await subscribe<RecoursNotification.SubscriptionEvent>({
name: 'notifications',
eventType: ['RecoursDemandé-V1', 'RecoursAnnulé-V1', 'RecoursAccordé-V1', 'RecoursRejeté-V1'],
eventHandler: async (event) => {
await mediator.publish<RecoursNotification.Execute>({
type: 'System.Notification.Éliminé.Recours',
data: event,
});
},
streamCategory: 'recours',
});

const unsubscribeÉliminéProjector = await subscribe<ÉliminéProjector.SubscriptionEvent>({
name: 'projector',
eventType: ['ÉliminéNotifié-V1', 'RebuildTriggered'],
Expand Down Expand Up @@ -88,6 +105,8 @@ export const setupEliminé = async ({ sendEmail }: SetupÉliminéDependenices) =

return async () => {
await unsubscribeRecoursProjector();
await unsubscribeRecoursNotification();

await unsubscribeÉliminéProjector();
await unsubscribeÉliminéNotification();
await unsubscribeÉliminéSaga();
Expand Down
1 change: 1 addition & 0 deletions packages/applications/notifications/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ export * as TâchePlanifiéeNotification from './subscribers/lauréat/tâchePlan
export * as LauréatNotification from './subscribers/lauréat/lauréat.notification';
export * as ÉliminéNotification from './subscribers/éliminé/éliminé.notification';
export * as PériodeNotification from './subscribers/période/période.notification';
export * as RecoursNotification from './subscribers/éliminé/recours.notification';

export { SendEmail, EmailPayload } from './sendEmail';
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { Message, MessageHandler, mediator } from 'mediateur';
import { match } from 'ts-pattern';

import { Option } from '@potentiel-libraries/monads';
import { Event } from '@potentiel-infrastructure/pg-event-sourcing';
import { Recours } from '@potentiel-domain/elimine';
import { IdentifiantProjet } from '@potentiel-domain/common';
import { Routes } from '@potentiel-applications/routes';
import {
CandidatureAdapter,
listerUtilisateursAdapter,
récupérerPorteursParIdentifiantProjetAdapter,
} from '@potentiel-infrastructure/domain-adapters';
import { Role } from '@potentiel-domain/utilisateur';

import { SendEmail } from '../../sendEmail';

export type SubscriptionEvent = Recours.RecoursEvent & Event;

export type Execute = Message<'System.Notification.Éliminé.Recours', SubscriptionEvent>;

const templateId = {
changementStatutRecours: 6310637,
recoursAccordéCRE: 6189222,
};

export type RegisterRecoursNotificationDependencies = {
sendEmail: SendEmail;
};

export const register = ({ sendEmail }: RegisterRecoursNotificationDependencies) => {
const handler: MessageHandler<Execute> = async (event) => {
const identifiantProjet = IdentifiantProjet.convertirEnValueType(
event.payload.identifiantProjet,
);

const projet = await CandidatureAdapter.récupérerProjetAdapter(identifiantProjet.formatter());
const porteurs = await récupérerPorteursParIdentifiantProjetAdapter(identifiantProjet);

if (Option.isNone(projet) || porteurs.length === 0 || !process.env.DGEC_EMAIL) {
return;
}
const { BASE_URL } = process.env;

const admins = [
{
email: process.env.DGEC_EMAIL,
fullName: 'DGEC',
},
];
const nomProjet = projet.nom;
const départementProjet = projet.localité.département;
const appelOffre = projet.appelOffre;
const période = projet.période;
const statut = match(event.type)
.with('RecoursDemandé-V1', () => 'demandée')
.with('RecoursAnnulé-V1', () => 'annulée')
.with('RecoursAccordé-V1', () => 'accordée')
.with('RecoursRejeté-V1', () => 'rejetée')
.exhaustive();

await sendEmail({
templateId: templateId.changementStatutRecours,
messageSubject: `Potentiel - Demande de recours ${statut} pour le projet ${nomProjet} (${appelOffre} période ${période})`,
recipients: [...porteurs, ...admins],
HubM marked this conversation as resolved.
Show resolved Hide resolved
variables: {
nom_projet: nomProjet,
departement_projet: départementProjet,
statut,
redirect_url:
statut === 'annulée'
? `${BASE_URL}${Routes.Projet.details(identifiantProjet.formatter())}`
: `${BASE_URL}${Routes.Recours.détail(identifiantProjet.formatter())}`,
},
});

if (event.type === 'RecoursAccordé-V1') {
const utilisateursCre = await listerUtilisateursAdapter([Role.cre.nom]);
const recipients = utilisateursCre.map(({ email, nomComplet }) => ({
email,
fullName: nomComplet,
}));

if (recipients.length > 0) {
await sendEmail({
templateId: templateId.recoursAccordéCRE,
messageSubject: `Potentiel - Un recours a été accepté pour le projet ${nomProjet} (${appelOffre} période ${période})`,
recipients,
variables: {
nom_projet: nomProjet,
modification_request_url: `${BASE_URL}${Routes.Recours.détail(identifiantProjet.formatter())}`,
},
});
}
}
};

mediator.register('System.Notification.Éliminé.Recours', handler);
};
2 changes: 1 addition & 1 deletion packages/infrastructure/email/src/sendEmail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,6 @@ export const sendEmail: SendEmail = async (sendEmailArgs) => {

getLogger().info('Email sent', sendEmailArgs);
} else {
getLogger().info('Emailing mode set to logging-only so no email was sent', sendEmailArgs);
getLogger().info('📨 Emailing mode set to logging-only so no email was sent', sendEmailArgs);
}
};