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

feat(api): 3853 - Notifier le jeune et les ref si un ref désiste un jeune #4669

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion api/src/__tests__/referent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ describe("Referent", () => {
);
expect(response.statusCode).toEqual(200);
expect(young?.status).toEqual("WITHDRAWN");
expect(young?.statusPhase1).toEqual("AFFECTED");
expect(young?.statusPhase1).toEqual("WAITING_AFFECTATION");
expect(young?.statusPhase2).toEqual("WAITING_REALISATION");
expect(young?.statusPhase3).toEqual("WAITING_REALISATION");
});
Expand Down
61 changes: 3 additions & 58 deletions api/src/controllers/young/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,7 @@ import {
MissionType,
ContractType,
CohortType,
SUB_ROLES,
ReferentType,
WITHRAWN_REASONS,
formatDateFRTimezoneUTC,
} from "snu-lib";
import { getFilteredSessionsForChangementSejour } from "../../cohort/cohortService";
import { anonymizeApplicationsFromYoungId } from "../../services/application";
Expand All @@ -77,6 +74,7 @@ import { FileTypeResult } from "file-type";
import { requestValidatorMiddleware } from "../../middlewares/requestValidatorMiddleware";
import { authMiddleware } from "../../middlewares/authMiddleware";
import { accessControlMiddleware } from "../../middlewares/accessControlMiddleware";
import { handleNotifForYoungWithdrawn } from "../../young/youngService";

const router = express.Router();
const YoungAuth = new AuthObject(YoungModel);
Expand Down Expand Up @@ -926,7 +924,8 @@ router.put("/withdraw", passport.authenticate("young", { session: false, failWit
}

const { withdrawnMessage, withdrawnReason } = value;
const oldStatusPhase1 = young.statusPhase1;

await handleNotifForYoungWithdrawn(young, cohort, withdrawnReason);

young.set({
status: YOUNG_STATUS.WITHDRAWN,
Expand All @@ -948,60 +947,6 @@ router.put("/withdraw", passport.authenticate("young", { session: false, failWit
if (bus) await updateSeatsTakenInBusLine(bus);
}

// We notify the ref dep and the young
try {
const youngFullName = young.firstName + " " + young.lastName;
const referents: ReferentDocument[] = await ReferentModel.find({ role: ROLES.REFERENT_DEPARTMENT, department: young.department });
const SUB_ROLES_PRIORITY = [SUB_ROLES.manager_department, SUB_ROLES.assistant_manager_department, SUB_ROLES.secretariat, SUB_ROLES.manager_phase2];
let selectedReferent: ReferentDocument | undefined = referents.find((referent) => referent.subRole && SUB_ROLES_PRIORITY.includes(referent.subRole));
if (!selectedReferent && referents.length > 0) {
selectedReferent = referents[0];
}
if (selectedReferent) {
await sendTemplate(SENDINBLUE_TEMPLATES.referent.YOUNG_WITHDRAWN_NOTIFICATION, {
emailTo: [{ name: `${selectedReferent.firstName} ${selectedReferent.lastName}`, email: selectedReferent.email }],
params: { student_name: youngFullName, message: WITHRAWN_REASONS.find((r) => r.value === withdrawnReason)?.label || "" },
});
}
// If they are CLE, we notify the class referent.
if (cohort?.type === YOUNG_SOURCE.CLE) {
const classe = await ClasseModel.findById(young.classeId);
const referent = await ReferentModel.findById(classe?.referentClasseIds[0]);
const datecohorte = `du ${formatDateFRTimezoneUTC(cohort.dateStart)} au ${formatDateFRTimezoneUTC(cohort.dateEnd)}`;
if (referent) {
await sendTemplate(SENDINBLUE_TEMPLATES.referent.YOUNG_WITHDRAWN_CLE, {
emailTo: [{ name: `${referent.firstName} ${referent.lastName}`, email: referent.email }],
params: {
youngFirstName: young.firstName,
youngLastName: young.lastName,
datecohorte,
raisondesistement: WITHRAWN_REASONS.find((r) => r.value === withdrawnReason)?.label || "",
},
});
}
}

// If young affected, we notify the head center
if (oldStatusPhase1 === YOUNG_STATUS_PHASE1.AFFECTED && young.sessionPhase1Id != null) {
const session = await SessionPhase1Model.findById(young.sessionPhase1Id);
const headCenter = await ReferentModel.findById(session?.headCenterId);

if (headCenter) {
await sendTemplate(SENDINBLUE_TEMPLATES.headCenter.YOUNG_WITHDRAWN, {
emailTo: [{ name: `${headCenter.firstName} ${headCenter.lastName}`, email: headCenter.email }],
params: { contact_name: youngFullName, message: WITHRAWN_REASONS.find((r) => r.value === withdrawnReason)?.label || "" },
});
}
}

await sendTemplate(SENDINBLUE_TEMPLATES.young.WITHDRAWN, {
emailTo: [{ name: `${young.firstName} ${young.lastName}`, email: young.email }],
params: { message: WITHRAWN_REASONS.find((r) => r.value === withdrawnReason)?.label || "" },
});
} catch (e) {
capture(e);
}

res.status(200).send({ ok: true, data: serializeYoung(updatedYoung, updatedYoung) });
} catch (error) {
capture(error);
Expand Down
9 changes: 7 additions & 2 deletions api/src/referent/referentController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ import {
getDepartmentForInscriptionGoal,
isAdmin,
isReferentReg,
isReferentDep,
canValidateYoungToLP,
} from "snu-lib";
import { getFilteredSessions, getAllSessions, getFilteredSessionsForCLE } from "../utils/cohort";
Expand All @@ -120,9 +119,9 @@ import { getCompletionObjectifs } from "../services/inscription-goal";
import SNUpport from "../SNUpport";
import { requestValidatorMiddleware } from "../middlewares/requestValidatorMiddleware";
import { accessControlMiddleware } from "../middlewares/accessControlMiddleware";
import { isAfter } from "date-fns/isAfter";
import { authMiddleware } from "../middlewares/authMiddleware";
import { CohortDocumentWithPlaces } from "../utils/cohort";
import { handleNotifForYoungWithdrawn } from "../young/youngService";

const router = express.Router();
const ReferentAuth = new AuthObject(ReferentModel);
Expand Down Expand Up @@ -675,6 +674,12 @@ router.put("/young/:id", passport.authenticate("referent", { session: false, fai
}
}

if (newYoung.status === YOUNG_STATUS.WITHDRAWN && young.status !== YOUNG_STATUS.WITHDRAWN) {
const { withdrawnReason } = newYoung;
await handleNotifForYoungWithdrawn(young, cohort, withdrawnReason);
newYoung.statusPhase1 = young.statusPhase1 === YOUNG_STATUS_PHASE1.AFFECTED ? YOUNG_STATUS_PHASE1.WAITING_AFFECTATION : young.statusPhase1;
}

young.set(newYoung);
await young.save({ fromUser: req.user });

Expand Down
80 changes: 77 additions & 3 deletions api/src/young/youngService.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
import { format } from "date-fns";

import { ERRORS, FUNCTIONAL_ERRORS, UserDto, YOUNG_PHASE, YOUNG_STATUS, YOUNG_STATUS_PHASE1, YoungDto, YoungType } from "snu-lib";

import { YoungDocument, YoungModel } from "../models";
import {
ERRORS,
FUNCTIONAL_ERRORS,
UserDto,
YOUNG_PHASE,
YOUNG_STATUS,
YOUNG_STATUS_PHASE1,
YoungDto,
YoungType,
SUB_ROLES,
WITHRAWN_REASONS,
formatDateFRTimezoneUTC,
YOUNG_SOURCE,
ROLES,
SENDINBLUE_TEMPLATES,
} from "snu-lib";
import { sendTemplate } from "../brevo";
import { YoungDocument, YoungModel, ReferentDocument, ReferentModel, ClasseModel, SessionPhase1Model } from "../models";
import { generatePdfIntoBuffer } from "../utils/pdf-renderer";

import { YOUNG_DOCUMENT, YOUNG_DOCUMENT_PHASE_TEMPLATE } from "./youngDocument";
import { isLocalTransport } from "./youngCertificateService";
import { logger } from "../logger";
import { capture } from "../sentry";

export const generateConvocationsForMultipleYoungs = async (youngs: YoungDto[]): Promise<Buffer> => {
const validatedYoungsWithSession = getValidatedYoungsWithSession(youngs);
Expand Down Expand Up @@ -169,3 +185,61 @@ export const mightAddInProgressStatus = async (young: YoungDocument, user: UserD
logger.info(`YoungService - mightAddInProgressStatus(), Status set to IN_PROGRESS for YoungId:${young.id}`);
}
};

export async function handleNotifForYoungWithdrawn(young, cohort, withdrawnReason) {
const oldStatusPhase1 = young.statusPhase1;

// We notify the ref dep and the young
try {
const youngFullName = young.firstName + " " + young.lastName;
const referents: ReferentDocument[] = await ReferentModel.find({ role: ROLES.REFERENT_DEPARTMENT, department: young.department });
const SUB_ROLES_PRIORITY = [SUB_ROLES.manager_department, SUB_ROLES.assistant_manager_department, SUB_ROLES.secretariat, SUB_ROLES.manager_phase2];
let selectedReferent: ReferentDocument | undefined = referents.find((referent) => referent.subRole && SUB_ROLES_PRIORITY.includes(referent.subRole));
if (!selectedReferent && referents.length > 0) {
selectedReferent = referents[0];
}
if (selectedReferent) {
await sendTemplate(SENDINBLUE_TEMPLATES.referent.YOUNG_WITHDRAWN_NOTIFICATION, {
emailTo: [{ name: `${selectedReferent.firstName} ${selectedReferent.lastName}`, email: selectedReferent.email }],
params: { student_name: youngFullName, message: WITHRAWN_REASONS.find((r) => r.value === withdrawnReason)?.label || "" },
});
}
// If they are CLE, we notify the class referent.
if (cohort?.type === YOUNG_SOURCE.CLE) {
const classe = await ClasseModel.findById(young.classeId);
const referent = await ReferentModel.findById(classe?.referentClasseIds[0]);
const datecohorte = `du ${formatDateFRTimezoneUTC(cohort.dateStart)} au ${formatDateFRTimezoneUTC(cohort.dateEnd)}`;
if (referent) {
await sendTemplate(SENDINBLUE_TEMPLATES.referent.YOUNG_WITHDRAWN_CLE, {
emailTo: [{ name: `${referent.firstName} ${referent.lastName}`, email: referent.email }],
params: {
youngFirstName: young.firstName,
youngLastName: young.lastName,
datecohorte,
raisondesistement: WITHRAWN_REASONS.find((r) => r.value === withdrawnReason)?.label || "",
},
});
}
}

// If young affected, we notify the head center
if (oldStatusPhase1 === YOUNG_STATUS_PHASE1.AFFECTED && young.sessionPhase1Id != null) {
const session = await SessionPhase1Model.findById(young.sessionPhase1Id);
const headCenter = await ReferentModel.findById(session?.headCenterId);

if (headCenter) {
await sendTemplate(SENDINBLUE_TEMPLATES.headCenter.YOUNG_WITHDRAWN, {
emailTo: [{ name: `${headCenter.firstName} ${headCenter.lastName}`, email: headCenter.email }],
params: { contact_name: youngFullName, message: WITHRAWN_REASONS.find((r) => r.value === withdrawnReason)?.label || "" },
});
}
}

await sendTemplate(SENDINBLUE_TEMPLATES.young.WITHDRAWN, {
emailTo: [{ name: `${young.firstName} ${young.lastName}`, email: young.email }],
params: { message: WITHRAWN_REASONS.find((r) => r.value === withdrawnReason)?.label || "" },
});
} catch (e) {
capture(e);
}
}
Loading