From 689df1d87087ed8817ea61c9cf7c1f1b046938e4 Mon Sep 17 00:00:00 2001 From: C2Chandelier Date: Thu, 30 Jan 2025 18:13:53 +0100 Subject: [PATCH] CLEtoCLE --- .../admin/core/sejours/jeune/Jeune.gateway.ts | 1 + .../admin/core/sejours/jeune/Jeune.model.ts | 8 +- .../admin/core/sejours/jeune/Jeune.service.ts | 4 +- .../PlanDeTransport.service.ts | 45 ++++ .../PlanDeTransportService.spec.ts | 0 .../bascule/__tests__/ServiceBascule.spec.ts | 0 .../sejours/phase1/bascule/service/index.ts | 167 +++++++++++++++ .../phase1/bascule/useCase/BasculeCLEtoCLE.ts | 193 +++++++++++++++++- .../phase1/bascule/useCase/BasculeCLEtoHTS.ts | 7 +- .../phase1/bascule/useCase/BasculeHTStoCLE.ts | 7 +- .../phase1/bascule/useCase/BasculeHTStoHTS.ts | 7 +- .../sejours/phase1/sejour/Sejour.Service.ts | 29 +++ .../phase1/sejour/SejourService.spec.ts | 0 .../sejours/phase1/session/Session.gateway.ts | 2 + .../sejours/phase1/session/Session.service.ts | 25 +++ .../phase1/session/SessionService.spec.ts | 0 .../sejours/jeune/repository/Jeune.mapper.ts | 5 +- .../repository/mongo/JeuneMongo.repository.ts | 5 + .../phase1/bascule/api/Bascule.controller.ts | 13 +- .../mongo/SessionMongo.repository.ts | 24 ++- apiv2/src/notification/core/Notification.ts | 36 ++++ .../infra/email/brevo/EmailBrevo.mapper.ts | 91 +++++++++ packages/lib/src/constants/inscription.ts | 10 + packages/lib/src/dto/youngDto.ts | 2 + 24 files changed, 656 insertions(+), 25 deletions(-) create mode 100644 apiv2/src/admin/core/sejours/phase1/PlanDeTransport/PlanDeTransport.service.ts create mode 100644 apiv2/src/admin/core/sejours/phase1/PlanDeTransport/PlanDeTransportService.spec.ts create mode 100644 apiv2/src/admin/core/sejours/phase1/bascule/__tests__/ServiceBascule.spec.ts create mode 100644 apiv2/src/admin/core/sejours/phase1/bascule/service/index.ts create mode 100644 apiv2/src/admin/core/sejours/phase1/sejour/Sejour.Service.ts create mode 100644 apiv2/src/admin/core/sejours/phase1/sejour/SejourService.spec.ts create mode 100644 apiv2/src/admin/core/sejours/phase1/session/Session.service.ts create mode 100644 apiv2/src/admin/core/sejours/phase1/session/SessionService.spec.ts create mode 100644 packages/lib/src/constants/inscription.ts diff --git a/apiv2/src/admin/core/sejours/jeune/Jeune.gateway.ts b/apiv2/src/admin/core/sejours/jeune/Jeune.gateway.ts index 5246a6a149..6c1c8096d1 100644 --- a/apiv2/src/admin/core/sejours/jeune/Jeune.gateway.ts +++ b/apiv2/src/admin/core/sejours/jeune/Jeune.gateway.ts @@ -23,6 +23,7 @@ export interface JeuneGateway { create(jeune: CreateJeuneModel): Promise; countAffectedByLigneDeBus(ligneDeBusId: string): Promise; findByClasseId(classeId: string): Promise; + find(query: any): Promise; } export const JeuneGateway = Symbol("JeuneGateway"); diff --git a/apiv2/src/admin/core/sejours/jeune/Jeune.model.ts b/apiv2/src/admin/core/sejours/jeune/Jeune.model.ts index 1d39192442..24e3d51550 100644 --- a/apiv2/src/admin/core/sejours/jeune/Jeune.model.ts +++ b/apiv2/src/admin/core/sejours/jeune/Jeune.model.ts @@ -29,13 +29,13 @@ interface Referent { role?: string; } -interface Note { +export type NoteType = { phase?: string; note?: string; referent?: Referent; createdAt?: Date; updatedAt?: Date; -} +}; export type JeuneModel = { id: string; @@ -168,6 +168,7 @@ export type JeuneModel = { autresTransportsMobilite?: string; formatMission?: string; engagement?: string; + cniFiles?: string[]; fichiers?: { cniFiles?: File[]; highSkilledActivityProofFiles?: File[]; @@ -195,7 +196,7 @@ export type JeuneModel = { missionsInMail?: { missionId?: string; date?: Date }[]; status_equivalence?: string; correctionRequests?: CorrectionRequest[]; - notes?: Note[]; + notes?: NoteType[]; hasNotes?: string; defenseInterest?: string; defenseTypeInterest?: string; @@ -261,6 +262,7 @@ export type JeuneModel = { departSejourMotif?: string; departSejourMotifComment?: string; youngPhase1Agreement: string; + cohesionStayMedicalFileReceived?: string; // Parent 1 Information parent1Prenom?: string; diff --git a/apiv2/src/admin/core/sejours/jeune/Jeune.service.ts b/apiv2/src/admin/core/sejours/jeune/Jeune.service.ts index 4f2c0312ed..6ede0be445 100644 --- a/apiv2/src/admin/core/sejours/jeune/Jeune.service.ts +++ b/apiv2/src/admin/core/sejours/jeune/Jeune.service.ts @@ -4,9 +4,9 @@ import { JeuneGateway } from "./Jeune.gateway"; @Injectable() export class JeuneService { - constructor(@Inject(JeuneGateway) private readonly classeGateway: JeuneGateway) {} + constructor(@Inject(JeuneGateway) private readonly jeuneGateway: JeuneGateway) {} findAll(): Promise { - return this.classeGateway.findAll(); + return this.jeuneGateway.findAll(); } } diff --git a/apiv2/src/admin/core/sejours/phase1/PlanDeTransport/PlanDeTransport.service.ts b/apiv2/src/admin/core/sejours/phase1/PlanDeTransport/PlanDeTransport.service.ts new file mode 100644 index 0000000000..127fe8e873 --- /dev/null +++ b/apiv2/src/admin/core/sejours/phase1/PlanDeTransport/PlanDeTransport.service.ts @@ -0,0 +1,45 @@ +import { Inject, Injectable } from "@nestjs/common"; +import { PlanDeTransportGateway } from "./PlanDeTransport.gateway"; +import { LigneDeBusGateway } from "../ligneDeBus/LigneDeBus.gateway"; +import { JeuneGateway } from "../../jeune/Jeune.gateway"; + +@Injectable() +export class PlanDeTransportService { + constructor( + @Inject(PlanDeTransportGateway) + @Inject(JeuneGateway) + @Inject(LigneDeBusGateway) + private readonly planDeTransportGateway: PlanDeTransportGateway, + private readonly jeuneGateway: JeuneGateway, + private readonly ligneDeBusGateway: LigneDeBusGateway, + ) {} + + async updateSeatsTakenInBusLine(busId: string) { + const ligneBus = await this.ligneDeBusGateway.findById(busId); + const jeuneDansLeBus = await this.jeuneGateway.find({ + $and: [ + { + status: "VALIDATED", + ligneId: busId, + }, + { + $or: [ + { statusPhase1: { $in: ["AFFECTED", "DONE"] } }, + { statusPhase1Tmp: { $in: ["AFFECTED", "DONE"] } }, + ], + }, + ], + }); + const placesPrises = jeuneDansLeBus.length; + if (ligneBus.placesOccupeesJeunes !== placesPrises) { + ligneBus.placesOccupeesJeunes = placesPrises; + await this.ligneDeBusGateway.update(ligneBus); + + const planTransport = await this.planDeTransportGateway.findById(busId); + planTransport.placesOccupeesJeunes = placesPrises; + planTransport.lineFillingRate = + planTransport.placesOccupeesJeunes && Math.floor((placesPrises / planTransport.capaciteJeunes) * 100); + await this.planDeTransportGateway.update(planTransport); + } + } +} diff --git a/apiv2/src/admin/core/sejours/phase1/PlanDeTransport/PlanDeTransportService.spec.ts b/apiv2/src/admin/core/sejours/phase1/PlanDeTransport/PlanDeTransportService.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apiv2/src/admin/core/sejours/phase1/bascule/__tests__/ServiceBascule.spec.ts b/apiv2/src/admin/core/sejours/phase1/bascule/__tests__/ServiceBascule.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apiv2/src/admin/core/sejours/phase1/bascule/service/index.ts b/apiv2/src/admin/core/sejours/phase1/bascule/service/index.ts new file mode 100644 index 0000000000..8e646e521d --- /dev/null +++ b/apiv2/src/admin/core/sejours/phase1/bascule/service/index.ts @@ -0,0 +1,167 @@ +import { Injectable, Inject } from "@nestjs/common"; +import { NoteType } from "@admin/core/sejours/jeune/Jeune.model"; +import { JeuneModel } from "@admin/core/sejours/jeune/Jeune.model"; +import { SessionModel } from "../../session/Session.model"; +import { ClasseModel } from "@admin/core/sejours/cle/classe/Classe.model"; +import { EtablissementModel } from "@admin/core/sejours/cle/etablissement/Etablissement.model"; +import { ReferentModel } from "@admin/core/iam/Referent.model"; +import { ReferentGateway } from "@admin/core/iam/Referent.gateway"; +import { YOUNG_SOURCE, getCohortPeriod } from "snu-lib"; +import { NotificationGateway } from "@notification/core/Notification.gateway"; +import { + EmailTemplate, + jeuneBasculeCLEParams, + jeuneBasculeParentNotifParams, + jeuneBasculeNotifToJeune, +} from "@notification/core/Notification"; +import configuration from "@config/configuration"; + +interface generateYoungNoteForBaculeProps { + jeune: JeuneModel; + session: SessionModel; + sessionChangeReason: string | null; + previousEtablissement: EtablissementModel; + previousClasse: ClasseModel; + newSource: keyof typeof YOUNG_SOURCE; + user: Partial; +} + +interface generateNotificationForBasculeProsp { + jeune: JeuneModel; + originaleSource: keyof typeof YOUNG_SOURCE; + session: SessionModel; + sessionChangeReason: string; + message: string; + classe: ClasseModel; +} + +@Injectable() +export class BasculeService { + constructor( + @Inject(ReferentGateway) private readonly referentGateway: ReferentGateway, + @Inject(NotificationGateway) private readonly notificationGateway: NotificationGateway, + ) {} + generateYoungNoteForBascule({ + jeune, + session, + sessionChangeReason, + previousClasse, + previousEtablissement, + newSource, + user, + }: generateYoungNoteForBaculeProps): NoteType { + const date = new Date(); + const newNote = { + note: ` + Changement de cohorte de ${jeune.sessionNom} (${jeune.source || YOUNG_SOURCE.VOLONTAIRE}) à ${ + session.nom + } (${newSource})${sessionChangeReason && ` pour la raison suivante : ${sessionChangeReason}`}.\n${ + previousEtablissement ? `Etablissement précédent : ${previousEtablissement.nom}.` : "" + }\n${previousClasse ? `Classe précédente : ${previousClasse.uniqueKeyAndId} ${previousClasse.nom}.` : ""}\n${ + jeune.centreId ? `Centre précédent : ${jeune.centreId}.` : "" + }\n${jeune.sejourId ? `Session précédente : ${jeune.sejourId}.` : ""}\n${ + jeune.pointDeRassemblementId ? `Point de rendez-vous précédent : ${jeune.pointDeRassemblementId}.` : "" + }\n${ + Object.prototype.hasOwnProperty.call(jeune, "presenceJDM") + ? `Présence JDM précédente : ${jeune.presenceJDM}.` + : "" + } + `.trim(), + phase: "PHASE_1", + createdAt: date, + updatedAt: date, + referent: { + _id: user.id, + firstName: user.prenom, + lastName: user.nom, + role: user.role, + }, + }; + return newNote; + } + + async generateNotificationForBascule({ + jeune, + originaleSource, + session, + sessionChangeReason, + message, + classe, + }: generateNotificationForBasculeProsp) { + const config = configuration(); + + if (jeune.source === YOUNG_SOURCE.CLE || originaleSource === YOUNG_SOURCE.CLE) { + const referentsClasse = await this.referentGateway.findByIds(classe.referentClasseIds); + const emailTo = referentsClasse.map((r) => ({ name: `${r.prenom} ${r.nom}`, email: r.email })); + + const params = { + to: emailTo, + firstname: jeune.prenom || "", + name: jeune.nom || "", + class_name: classe.nom || "", + class_code: classe.uniqueKeyAndId, + cta: `${config.urls.admin}/classes/${classe.id?.toString()}`, + }; + + // Bascule vers CLE + if (jeune.source === YOUNG_SOURCE.CLE) { + await this.notificationGateway.sendEmail( + params, + EmailTemplate.JEUNE_CHANGE_SESSION_TO_CLE, + ); + } + + // Bascule CLE > HTS + if (jeune.source === YOUNG_SOURCE.VOLONTAIRE && originaleSource === YOUNG_SOURCE.CLE) { + await this.notificationGateway.sendEmail( + params, + EmailTemplate.JEUNE_CHANGE_SESSION_CLE_TO_HTS, + ); + } + } + + const emailsTo: { name: string; email: string }[] = []; + if (jeune.autorisationSNUParent1 === "true") + emailsTo.push({ name: `${jeune.parent1Prenom} ${jeune.parent1Nom}`, email: jeune.parent1Email || "" }); + if (jeune.autorisationSNUParent2 === "true") + emailsTo.push({ name: `${jeune.parent2Prenom} ${jeune.parent2Nom}`, email: jeune.parent2Email || "" }); + if (emailsTo.length !== 0) { + const params = { + to: emailsTo, + cohort: session.nom, + youngFirstName: jeune.prenom || "", + youngName: jeune.nom || "", + cta: config.urls.app || "", + }; + await this.notificationGateway.sendEmail( + params, + EmailTemplate.JEUNE_CHANGE_SESSION_CLE_TO_HTS, + ); + } + + const sessionPeriod = getCohortPeriod({ + name: session.nom, + dateStart: session.dateStart, + dateEnd: session.dateEnd, + }); + const programs = { + [YOUNG_SOURCE.VOLONTAIRE]: "Volontaire hors temps scolaire (HTS)", + [YOUNG_SOURCE.CLE]: "Classe engagée (CLE)", + }; + + const params = { + to: [{ name: `${jeune.prenom} ${jeune.nom}`, email: jeune.email }], + motif: sessionChangeReason, + message, + newcohortdate: sessionPeriod, + oldprogram: programs[originaleSource], + newprogram: jeune.source !== originaleSource ? programs[jeune.source] : "", + cta: config.urls.app || "", + }; + + await this.notificationGateway.sendEmail( + params, + EmailTemplate.JEUNE_CHANGE_SESSION_CLE_TO_HTS, + ); + } +} diff --git a/apiv2/src/admin/core/sejours/phase1/bascule/useCase/BasculeCLEtoCLE.ts b/apiv2/src/admin/core/sejours/phase1/bascule/useCase/BasculeCLEtoCLE.ts index b048c68e47..dc4b4b4670 100644 --- a/apiv2/src/admin/core/sejours/phase1/bascule/useCase/BasculeCLEtoCLE.ts +++ b/apiv2/src/admin/core/sejours/phase1/bascule/useCase/BasculeCLEtoCLE.ts @@ -1,17 +1,200 @@ import { Inject, Injectable } from "@nestjs/common"; import { UseCase } from "@shared/core/UseCase"; import { JeuneGateway } from "../../../jeune/Jeune.gateway"; -import { JeuneModel } from "../../../jeune/Jeune.model"; +import { ClasseGateway } from "@admin/core/sejours/cle/classe/Classe.gateway"; +import { EtablissementGateway } from "@admin/core/sejours/cle/etablissement/Etablissement.gateway"; +import { SessionGateway } from "../../session/Session.gateway"; import { ChangerLaSessionDuJeunePayloadDto } from "@admin/infra/sejours/phase1/bascule/api/Bascule.validation"; import { JeuneMapper } from "@admin/infra/sejours/jeune/repository/Jeune.mapper"; -import { YoungDto } from "snu-lib"; +import { YoungDto, YOUNG_SOURCE, YOUNG_STATUS, YOUNG_STATUS_PHASE1, CLE_FILIERE, YOUNG_SITUATIONS } from "snu-lib"; +import { STEPS2023 } from "snu-lib/src/constants/inscription"; +import { SessionService } from "../../session/Session.service"; +import { ReferentModel } from "@admin/core/iam/Referent.model"; +import { BasculeService } from "../service"; +import { SejourService } from "../../sejour/Sejour.Service"; +import { PlanDeTransportService } from "../../PlanDeTransport/PlanDeTransport.service"; @Injectable() export class BasculeCLEtoCLE implements UseCase { - constructor(@Inject(JeuneGateway) private readonly jeuneGateway: JeuneGateway) {} - async execute(jeuneId: string, payload: ChangerLaSessionDuJeunePayloadDto): Promise { - console.log("BasculeCLEtoCLE.execute", payload); + constructor( + @Inject(JeuneGateway) private readonly jeuneGateway: JeuneGateway, + @Inject(ClasseGateway) private readonly classeGateway: ClasseGateway, + @Inject(EtablissementGateway) private readonly etablissementGateway: EtablissementGateway, + @Inject(SessionGateway) private readonly sessionGateway: SessionGateway, + private readonly sessionService: SessionService, + private readonly basculeService: BasculeService, + private readonly sejourService: SejourService, + private readonly planDeTransportService: PlanDeTransportService, + ) {} + async execute( + jeuneId: string, + payload: ChangerLaSessionDuJeunePayloadDto, + user: Partial, + ): Promise { + if (payload.source !== YOUNG_SOURCE.CLE || !payload.classeId || !payload.etablissementId) { + throw new Error("Invalid payload"); + } + const jeune = await this.jeuneGateway.findById(jeuneId); + if (jeune.source !== YOUNG_SOURCE.CLE || !jeune.classeId || !jeune.etablissementId) { + throw new Error("Invalid object jeune"); + } + const classe = await this.classeGateway.findById(payload.classeId); + if (!classe.sessionId) { + throw new Error("Classe has no session"); + } + if (classe.placesPrises >= classe.placesTotal) { + throw new Error("Classe is full"); + } + const etablissement = await this.etablissementGateway.findById(payload.etablissementId); + const session = await this.sessionGateway.findById(classe.sessionId); + const availableSession = await this.sessionService.getFilteredSessionsForCLE(); + if (!availableSession.some(({ nom }) => nom === session.nom)) { + throw new Error("Session not available"); + } + const ancienneClasse = await this.classeGateway.findById(jeune.classeId); + const ancienEtablissement = await this.etablissementGateway.findById(jeune.etablissementId); + const oldSessionPhase1Id = jeune.sejourId; + const oldBusId = jeune.ligneDeBusId; + const originaleSource = jeune.source; + + let inscriptionStep = jeune.etapeInscription2023; + let reinscriptionStep = jeune.etapeReinscription2023; + if ( + jeune.statut === YOUNG_STATUS.IN_PROGRESS && + (jeune.etapeInscription2023 === STEPS2023.DOCUMENTS || jeune.etapeReinscription2023 === STEPS2023.DOCUMENTS) + ) { + jeune.aCommenceReinscription + ? (reinscriptionStep = STEPS2023.REPRESENTANTS) + : (inscriptionStep = STEPS2023.REPRESENTANTS); + } + + let statutPhase1 = jeune.statutPhase1; + let hasMeetingInformation = jeune.hasMeetingInformation; + if (classe.centreCohesionId && classe.sessionId && classe.pointDeRassemblementId) { + hasMeetingInformation = "true"; + statutPhase1 = YOUNG_STATUS_PHASE1.AFFECTED; + } + + const correctionRequestsFiltered = + jeune.correctionRequests?.filter((correction) => correction.field !== "CniFile") || []; + + const newNote = this.basculeService.generateYoungNoteForBascule({ + jeune, + session, + sessionChangeReason: null, + previousClasse: ancienneClasse, + previousEtablissement: ancienEtablissement, + newSource: payload.source, + user, + }); + + if (jeune.sejourId || jeune.pointDeRassemblementId) { + jeune.originalSessionNom = jeune.sessionNom; + jeune.originalSessionId = jeune.sessionId; + jeune.statut = BasculeCLEtoCLE.getStatutJeuneForBasculeCLEtoCLE(jeune.statut); + jeune.statutPhase1 = statutPhase1; + jeune.sessionNom = classe.sessionNom; + jeune.sessionId = classe.sessionId; + jeune.centreId = classe.centreCohesionId; + jeune.sejourId = classe.sessionId; + jeune.etablissementId = etablissement.id; + jeune.pointDeRassemblementId = classe.pointDeRassemblementId; + jeune.ligneDeBusId = classe.ligneId; + jeune.deplacementPhase1Autonomous = undefined; + jeune.transportInfoGivenByLocal = undefined; + jeune.cohesionStayPresence = undefined; + jeune.presenceJDM = undefined; + jeune.departInform = undefined; + jeune.departSejourAt = undefined; + jeune.departSejourMotif = undefined; + jeune.departSejourMotifComment = undefined; + jeune.youngPhase1Agreement = "false"; + jeune.hasMeetingInformation = hasMeetingInformation; + jeune.cohesionStayMedicalFileReceived = undefined; + jeune.cohesionStayPresence = undefined; + jeune.source = YOUNG_SOURCE.CLE; + jeune.cniFiles = []; + jeune.fichiers = jeune.fichiers || {}; + jeune.fichiers.cniFiles = []; + jeune.etapeInscription2023 = inscriptionStep; + jeune.etapeReinscription2023 = reinscriptionStep; + jeune.dateExpirationDernierFichierCNI = undefined; + jeune.categorieDernierFichierCNI = undefined; + jeune.correctionRequests = correctionRequestsFiltered; + jeune.scolarise = "true"; + jeune.nomEtablissement = etablissement.nom; + jeune.typeEtablissement = etablissement.type[0]; + jeune.adresseEtablissement = etablissement.adresse; + jeune.codePostalEtablissement = etablissement.codePostal; + jeune.villeEtablissement = etablissement.commune; + jeune.departementEtablissement = etablissement.departement; + jeune.regionEtablissement = etablissement.region; + jeune.paysEtablissement = etablissement.pays; + jeune.ecoleRamsesId = undefined; + jeune.situation = BasculeCLEtoCLE.getYoungSituationIfCLE(classe.filiere || ""); + jeune.hasMeetingInformation = hasMeetingInformation; + jeune.notes = [...(jeune.notes ?? []), newNote]; + jeune.hasNotes = "true"; + } + + await this.jeuneGateway.update(jeune); + + //await ClasseStateManager.compute(ancienneClasse.id, user, { YoungModel }); + //await ClasseStateManager.compute(classe.id, user, { YoungModel }); + + // if they had a session, we check if we need to update the places taken / left + if (oldSessionPhase1Id) { + await this.sejourService.updatePlacesSessionPhase1(oldSessionPhase1Id); + } + + // if they had a meetingPoint, we check if we need to update the places taken / left in the bus + if (oldBusId) { + await this.planDeTransportService.updateSeatsTakenInBusLine(oldBusId); + } + + /* await this.notificationGateway.sendEmail( + params, + EmailTemplate.VERIFIER_CLASSE_EMAIL_ADMIN_CLE, + ); */ + + /* emailsEmitter.emit(SENDINBLUE_TEMPLATES.young.CHANGE_COHORT, { + young, + previousYoung, + cohortName: cohort, + cohortChangeReason, + message: payload.message, + classe, + }); */ + return JeuneMapper.toDto(jeune); } + + static getStatutJeuneForBasculeCLEtoCLE(statut: string): string { + switch (statut) { + case YOUNG_STATUS.IN_PROGRESS: + return YOUNG_STATUS.IN_PROGRESS; + default: + return YOUNG_STATUS.WAITING_VALIDATION; + } + } + + static getYoungSituationIfCLE(filiere: string): string { + if (filiere === CLE_FILIERE.GENERAL_AND_TECHNOLOGIC) { + return YOUNG_SITUATIONS.GENERAL_SCHOOL; + } + if (filiere === CLE_FILIERE.PROFESSIONAL) { + return YOUNG_SITUATIONS.PROFESSIONAL_SCHOOL; + } + if (filiere === CLE_FILIERE.APPRENTICESHIP) { + return YOUNG_SITUATIONS.APPRENTICESHIP; + } + if (filiere === CLE_FILIERE.ADAPTED) { + return YOUNG_SITUATIONS.SPECIALIZED_SCHOOL; + } + if (filiere === CLE_FILIERE.MIXED) { + return YOUNG_SITUATIONS.GENERAL_SCHOOL; + } + return filiere; + } } diff --git a/apiv2/src/admin/core/sejours/phase1/bascule/useCase/BasculeCLEtoHTS.ts b/apiv2/src/admin/core/sejours/phase1/bascule/useCase/BasculeCLEtoHTS.ts index a0ea415aac..7984d3f0bc 100644 --- a/apiv2/src/admin/core/sejours/phase1/bascule/useCase/BasculeCLEtoHTS.ts +++ b/apiv2/src/admin/core/sejours/phase1/bascule/useCase/BasculeCLEtoHTS.ts @@ -4,11 +4,16 @@ import { JeuneGateway } from "../../../jeune/Jeune.gateway"; import { ChangerLaSessionDuJeunePayloadDto } from "@admin/infra/sejours/phase1/bascule/api/Bascule.validation"; import { JeuneMapper } from "@admin/infra/sejours/jeune/repository/Jeune.mapper"; import { YoungDto } from "snu-lib"; +import { ReferentModel } from "@admin/core/iam/Referent.model"; @Injectable() export class BasculeCLEtoHTS implements UseCase { constructor(@Inject(JeuneGateway) private readonly jeuneGateway: JeuneGateway) {} - async execute(jeuneId: string, payload: ChangerLaSessionDuJeunePayloadDto): Promise { + async execute( + jeuneId: string, + payload: ChangerLaSessionDuJeunePayloadDto, + user: Partial, + ): Promise { console.log("BasculeCLEtoHTS.execute", payload); const jeune = await this.jeuneGateway.findById(jeuneId); return JeuneMapper.toDto(jeune); diff --git a/apiv2/src/admin/core/sejours/phase1/bascule/useCase/BasculeHTStoCLE.ts b/apiv2/src/admin/core/sejours/phase1/bascule/useCase/BasculeHTStoCLE.ts index a7edb0239d..4cf16b4efc 100644 --- a/apiv2/src/admin/core/sejours/phase1/bascule/useCase/BasculeHTStoCLE.ts +++ b/apiv2/src/admin/core/sejours/phase1/bascule/useCase/BasculeHTStoCLE.ts @@ -4,11 +4,16 @@ import { JeuneGateway } from "../../../jeune/Jeune.gateway"; import { ChangerLaSessionDuJeunePayloadDto } from "@admin/infra/sejours/phase1/bascule/api/Bascule.validation"; import { JeuneMapper } from "@admin/infra/sejours/jeune/repository/Jeune.mapper"; import { YoungDto } from "snu-lib"; +import { ReferentModel } from "@admin/core/iam/Referent.model"; @Injectable() export class BasculeHTStoCLE implements UseCase { constructor(@Inject(JeuneGateway) private readonly jeuneGateway: JeuneGateway) {} - async execute(jeuneId: string, payload: ChangerLaSessionDuJeunePayloadDto): Promise { + async execute( + jeuneId: string, + payload: ChangerLaSessionDuJeunePayloadDto, + user: Partial, + ): Promise { console.log("BasculeHTStoCLE.execute", payload); const jeune = await this.jeuneGateway.findById(jeuneId); return JeuneMapper.toDto(jeune); diff --git a/apiv2/src/admin/core/sejours/phase1/bascule/useCase/BasculeHTStoHTS.ts b/apiv2/src/admin/core/sejours/phase1/bascule/useCase/BasculeHTStoHTS.ts index c05b085be6..8cf74b4f1a 100644 --- a/apiv2/src/admin/core/sejours/phase1/bascule/useCase/BasculeHTStoHTS.ts +++ b/apiv2/src/admin/core/sejours/phase1/bascule/useCase/BasculeHTStoHTS.ts @@ -4,11 +4,16 @@ import { JeuneGateway } from "../../../jeune/Jeune.gateway"; import { ChangerLaSessionDuJeunePayloadDto } from "@admin/infra/sejours/phase1/bascule/api/Bascule.validation"; import { JeuneMapper } from "@admin/infra/sejours/jeune/repository/Jeune.mapper"; import { YoungDto } from "snu-lib"; +import { ReferentModel } from "@admin/core/iam/Referent.model"; @Injectable() export class BasculeHTStoHTS implements UseCase { constructor(@Inject(JeuneGateway) private readonly jeuneGateway: JeuneGateway) {} - async execute(jeuneId: string, payload: ChangerLaSessionDuJeunePayloadDto): Promise { + async execute( + jeuneId: string, + payload: ChangerLaSessionDuJeunePayloadDto, + user: Partial, + ): Promise { console.log("BasculeHTStoHTS.execute", payload); const jeune = await this.jeuneGateway.findById(jeuneId); return JeuneMapper.toDto(jeune); diff --git a/apiv2/src/admin/core/sejours/phase1/sejour/Sejour.Service.ts b/apiv2/src/admin/core/sejours/phase1/sejour/Sejour.Service.ts new file mode 100644 index 0000000000..6780b6702d --- /dev/null +++ b/apiv2/src/admin/core/sejours/phase1/sejour/Sejour.Service.ts @@ -0,0 +1,29 @@ +import { Inject, Injectable } from "@nestjs/common"; +import { SejourGateway } from "./Sejour.gateway"; +import { JeuneGateway } from "../../jeune/Jeune.gateway"; + +@Injectable() +export class SejourService { + constructor( + @Inject(SejourGateway) + @Inject(JeuneGateway) + private readonly sejourGateway: SejourGateway, + private readonly jeuneGateway: JeuneGateway, + ) {} + + async updatePlacesSessionPhase1(idSejour: string) { + const sejour = await this.sejourGateway.findById(idSejour); + const jeunes = await this.jeuneGateway.findBySessionId(idSejour); + const placesTaken = jeunes.filter( + (jeune) => + ["AFFECTED", "DONE"].includes(jeune.statutPhase1) && + jeune.cohesionStayPresence !== "false" && + jeune.statut === "VALIDATED", + ).length; + const placesLeft = Math.max(0, (sejour.placesTotal || 0) - placesTaken); + if (sejour.placesRestantes !== placesLeft) { + sejour.placesRestantes = placesLeft; + await this.sejourGateway.update(sejour); + } + } +} diff --git a/apiv2/src/admin/core/sejours/phase1/sejour/SejourService.spec.ts b/apiv2/src/admin/core/sejours/phase1/sejour/SejourService.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apiv2/src/admin/core/sejours/phase1/session/Session.gateway.ts b/apiv2/src/admin/core/sejours/phase1/session/Session.gateway.ts index ce5f4d17bc..6fa060f202 100644 --- a/apiv2/src/admin/core/sejours/phase1/session/Session.gateway.ts +++ b/apiv2/src/admin/core/sejours/phase1/session/Session.gateway.ts @@ -1,8 +1,10 @@ import { CreateSessionModel, SessionModel } from "./Session.model"; +import { COHORT_TYPE, COHORT_STATUS } from "snu-lib"; export interface SessionGateway { findById(id: string): Promise; findBySnuId(snuId: string): Promise; create(session: CreateSessionModel): Promise; + findByElligibility(type: keyof typeof COHORT_TYPE, statut: keyof typeof COHORT_STATUS): Promise; } export const SessionGateway = Symbol("SessionGateway"); diff --git a/apiv2/src/admin/core/sejours/phase1/session/Session.service.ts b/apiv2/src/admin/core/sejours/phase1/session/Session.service.ts new file mode 100644 index 0000000000..f63be63ba8 --- /dev/null +++ b/apiv2/src/admin/core/sejours/phase1/session/Session.service.ts @@ -0,0 +1,25 @@ +import { Inject, Injectable } from "@nestjs/common"; +import { SessionGateway } from "../session/Session.gateway"; +import { SessionModel } from "../session/Session.model"; +import { COHORT_STATUS, COHORT_TYPE } from "snu-lib"; + +@Injectable() +export class SessionService { + constructor( + @Inject(SessionGateway) + private readonly sessionGateway: SessionGateway, + ) {} + + async getFilteredSessionsForCLE(): Promise { + const sessionsCLE = await this.sessionGateway.findByElligibility(COHORT_TYPE.CLE, COHORT_STATUS.PUBLISHED); + let now = new Date(); + const sessions = sessionsCLE.filter( + (session) => + !!session.inscriptionStartDate && + session.inscriptionStartDate <= now && + ((session.inscriptionEndDate && session.inscriptionEndDate > now) || + (session.instructionEndDate && session.instructionEndDate > now)), + ); + return sessions; + } +} diff --git a/apiv2/src/admin/core/sejours/phase1/session/SessionService.spec.ts b/apiv2/src/admin/core/sejours/phase1/session/SessionService.spec.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apiv2/src/admin/infra/sejours/jeune/repository/Jeune.mapper.ts b/apiv2/src/admin/infra/sejours/jeune/repository/Jeune.mapper.ts index b06005146c..17f15f8ea0 100644 --- a/apiv2/src/admin/infra/sejours/jeune/repository/Jeune.mapper.ts +++ b/apiv2/src/admin/infra/sejours/jeune/repository/Jeune.mapper.ts @@ -195,6 +195,7 @@ export class JeuneMapper { lat: jeuneDocument.medicosocialStructureLocation?.lat, lon: jeuneDocument.medicosocialStructureLocation?.lon, }, + cohesionStayMedicalFileReceived: jeuneDocument.cohesionStayMedicalFileReceived, structureEngagee: jeuneDocument.engagedStructure, memeEcoleCLE: jeuneDocument.sameSchoolCLE, amenagementSpecifique: jeuneDocument.specificAmenagment, @@ -254,7 +255,7 @@ export class JeuneMapper { fichiersPreparationMilitaireCertificat: jeuneDocument.militaryPreparationFilesCertificate, statutFichiersPreparationMilitaire: jeuneDocument.statusMilitaryPreparationFiles, messageCorrectionPreparationMilitaire: jeuneDocument.militaryPreparationCorrectionMessage, - + cniFiles: jeuneDocument.cniFiles, fichiers: { cniFiles: jeuneDocument.files?.cniFiles, highSkilledActivityProofFiles: jeuneDocument.files.highSkilledActivityProofFiles, @@ -653,6 +654,7 @@ export class JeuneMapper { militaryPreparationFilesCertificate: jeune.fichiersPreparationMilitaireCertificat, statusMilitaryPreparationFiles: jeune.statutFichiersPreparationMilitaire, militaryPreparationCorrectionMessage: jeune.messageCorrectionPreparationMilitaire, + cniFiles: jeune.cniFiles, files: { cniFiles: jeune.fichiers?.cniFiles, highSkilledActivityProofFiles: jeune.fichiers?.highSkilledActivityProofFiles, @@ -671,6 +673,7 @@ export class JeuneMapper { latestCNIFileCategory: jeune.categorieDernierFichierCNI, missionsInMail: jeune.missionsInMail, youngPhase1Agreement: jeune.youngPhase1Agreement, + cohesionStayMedicalFileReceived: jeune.cohesionStayMedicalFileReceived, status_equivalence: jeune.status_equivalence, correctionRequests: jeune.correctionRequests, notes: jeune.notes, diff --git a/apiv2/src/admin/infra/sejours/jeune/repository/mongo/JeuneMongo.repository.ts b/apiv2/src/admin/infra/sejours/jeune/repository/mongo/JeuneMongo.repository.ts index d3963a554e..7ab48f481a 100644 --- a/apiv2/src/admin/infra/sejours/jeune/repository/mongo/JeuneMongo.repository.ts +++ b/apiv2/src/admin/infra/sejours/jeune/repository/mongo/JeuneMongo.repository.ts @@ -152,4 +152,9 @@ export class JeuneRepository implements JeuneGateway { ], }); } + + async find(): Promise { + const jeunes = await this.jeuneMongooseEntity.find(); + return JeuneMapper.toModels(jeunes); + } } diff --git a/apiv2/src/admin/infra/sejours/phase1/bascule/api/Bascule.controller.ts b/apiv2/src/admin/infra/sejours/phase1/bascule/api/Bascule.controller.ts index 4c10cea2b4..f10730bd21 100644 --- a/apiv2/src/admin/infra/sejours/phase1/bascule/api/Bascule.controller.ts +++ b/apiv2/src/admin/infra/sejours/phase1/bascule/api/Bascule.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Put, Param, UseGuards, Body, Inject } from "@nestjs/common"; +import { Controller, Put, Param, UseGuards, Body, Inject, Request } from "@nestjs/common"; import { YOUNG_SOURCE, Phase1Routes } from "snu-lib"; import { JeuneGateway } from "@admin/core/sejours/jeune/Jeune.gateway"; @@ -9,6 +9,7 @@ import { BasculeHTStoHTS } from "@admin/core/sejours/phase1/bascule/useCase/Basc import { JeuneReferentGuard } from "../../../jeune/guard/JeuneReferent.guard"; import { ChangerLaSessionDuJeunePayloadDto } from "./Bascule.validation"; +import { CustomRequest } from "@shared/infra/CustomRequest"; @Controller("Bascule") export class BasculeController { @@ -25,20 +26,22 @@ export class BasculeController { async changeCohort( @Param("id") id: string, @Body() changerLaSessionDuJeune: ChangerLaSessionDuJeunePayloadDto, + @Request() request: CustomRequest, ): Promise { + const user = request.user; const jeune = await this.jeuneGateway.findById(id); if (jeune.source === YOUNG_SOURCE.CLE && changerLaSessionDuJeune.source === YOUNG_SOURCE.CLE) { - return this.basculeCLEtoCLE.execute(id, changerLaSessionDuJeune); + return this.basculeCLEtoCLE.execute(id, changerLaSessionDuJeune, user); } else if (jeune.source === YOUNG_SOURCE.CLE && changerLaSessionDuJeune.source === YOUNG_SOURCE.VOLONTAIRE) { - return this.basculeCLEtoHTS.execute(id, changerLaSessionDuJeune); + return this.basculeCLEtoHTS.execute(id, changerLaSessionDuJeune, user); } else if (jeune.source === YOUNG_SOURCE.VOLONTAIRE && changerLaSessionDuJeune.source === YOUNG_SOURCE.CLE) { - return this.basculeHTStoCLE.execute(id, changerLaSessionDuJeune); + return this.basculeHTStoCLE.execute(id, changerLaSessionDuJeune, user); } else if ( jeune.source === YOUNG_SOURCE.VOLONTAIRE && changerLaSessionDuJeune.source === YOUNG_SOURCE.VOLONTAIRE ) { - return this.basculeHTStoHTS.execute(id, changerLaSessionDuJeune); + return this.basculeHTStoHTS.execute(id, changerLaSessionDuJeune, user); } else { throw new Error("Unhandled source combination"); } diff --git a/apiv2/src/admin/infra/sejours/phase1/session/repository/mongo/SessionMongo.repository.ts b/apiv2/src/admin/infra/sejours/phase1/session/repository/mongo/SessionMongo.repository.ts index 97f9b4389b..90a68e55fe 100644 --- a/apiv2/src/admin/infra/sejours/phase1/session/repository/mongo/SessionMongo.repository.ts +++ b/apiv2/src/admin/infra/sejours/phase1/session/repository/mongo/SessionMongo.repository.ts @@ -7,15 +7,16 @@ import { SESSION_MONGOOSE_ENTITY, SessionDocument } from "../../provider/Session import { SessionMapper } from "../Session.mapper"; import { SessionGateway } from "@admin/core/sejours/phase1/session/Session.gateway"; import { CreateSessionModel, SessionModel } from "@admin/core/sejours/phase1/session/Session.model"; +import { COHORT_TYPE, COHORT_STATUS } from "snu-lib"; @Injectable() export class SessionRepository implements SessionGateway { constructor( - @Inject(SESSION_MONGOOSE_ENTITY) private sesssionMongooseEntity: Model, + @Inject(SESSION_MONGOOSE_ENTITY) private sessionMongooseEntity: Model, private readonly cls: ClsService, ) {} async findBySnuId(snuId: string): Promise { - const session = await this.sesssionMongooseEntity.findOne({ snuId }); + const session = await this.sessionMongooseEntity.findOne({ snuId }); if (!session) { return null; } @@ -24,12 +25,12 @@ export class SessionRepository implements SessionGateway { async create(session: CreateSessionModel): Promise { const sessionEntity = SessionMapper.toEntityCreate(session); - const createdSession = await this.sesssionMongooseEntity.create(sessionEntity); + const createdSession = await this.sessionMongooseEntity.create(sessionEntity); return SessionMapper.toModel(createdSession); } async findById(id: string): Promise { - const session = await this.sesssionMongooseEntity.findById(id); + const session = await this.sessionMongooseEntity.findById(id); if (!session) { throw new FunctionalException(FunctionalExceptionCode.NOT_FOUND); } @@ -37,7 +38,7 @@ export class SessionRepository implements SessionGateway { } async update(session: SessionModel): Promise { const sessionEntity = SessionMapper.toEntity(session); - const retrievedSession = await this.sesssionMongooseEntity.findById(session.id); + const retrievedSession = await this.sessionMongooseEntity.findById(session.id); if (!retrievedSession) { throw new FunctionalException(FunctionalExceptionCode.NOT_FOUND); } @@ -50,7 +51,18 @@ export class SessionRepository implements SessionGateway { } async findAll(): Promise { - const sessions = await this.sesssionMongooseEntity.find(); + const sessions = await this.sessionMongooseEntity.find(); + return SessionMapper.toModels(sessions); + } + + async findByElligibility( + type: keyof typeof COHORT_TYPE, + statut: keyof typeof COHORT_STATUS, + ): Promise { + const sessions = await this.sessionMongooseEntity.find({ type, statut }); + if (!sessions || sessions.length === 0) { + throw new FunctionalException(FunctionalExceptionCode.NOT_FOUND); + } return SessionMapper.toModels(sessions); } } diff --git a/apiv2/src/notification/core/Notification.ts b/apiv2/src/notification/core/Notification.ts index 4ae49d92f8..4455c8fe76 100644 --- a/apiv2/src/notification/core/Notification.ts +++ b/apiv2/src/notification/core/Notification.ts @@ -1,3 +1,5 @@ +import exp from "constants"; + export interface EmailParams { from?: string; to: { email: string; name: string }[]; @@ -40,6 +42,30 @@ export interface SupprimerClasseEngageeParams extends EmailParams { export interface NouvelleClasseEngageeParams extends SupprimerClasseEngageeParams {} +export interface jeuneBasculeCLEParams extends EmailParams { + firstname: string; + name: string; + class_name: string; + class_code: string; + cta: string; +} + +export interface jeuneBasculeParentNotifParams extends EmailParams { + cohort: string; + youngFirstName: string; + youngName: string; + cta: string; +} + +export interface jeuneBasculeNotifToJeune extends EmailParams { + motif: string; + message: string; + newcohortdate: string; + oldprogram: string; + newprogram: string; + cta: string; +} + export enum EmailTemplate { // CLE VERIFIER_CLASSE_EMAIL_ADMIN_CLE = "2084", @@ -50,4 +76,14 @@ export enum EmailTemplate { SUPPRIMER_CLASSE_ENGAGEE = "2331", NOUVELLE_CLASSE_ENGAGEE = "2350", IMPORT_REFERENTIEL_GENERIQUE = "2324", + + // Referent + JEUNE_CHANGE_SESSION_TO_CLE = "1462", + JEUNE_CHANGE_SESSION_CLE_TO_HTS = "1463", + + // Jeune + CHANGE_SESSION = "1461", + + // Parent + PARENT_JEUNE_SESSION_CHANGE = "1307", } diff --git a/apiv2/src/notification/infra/email/brevo/EmailBrevo.mapper.ts b/apiv2/src/notification/infra/email/brevo/EmailBrevo.mapper.ts index 9305657ac5..d964431acf 100644 --- a/apiv2/src/notification/infra/email/brevo/EmailBrevo.mapper.ts +++ b/apiv2/src/notification/infra/email/brevo/EmailBrevo.mapper.ts @@ -5,6 +5,9 @@ import { SupprimerClasseEngageeParams, VerifierClasseEmailAdminCleParams, VerifierClasseEmailReferentDepRegParams, + jeuneBasculeCLEParams, + jeuneBasculeParentNotifParams, + jeuneBasculeNotifToJeune, } from "@notification/core/Notification"; import { EmailProviderParams } from "./EmailBrevo.provider"; @@ -33,6 +36,13 @@ export class EmailBrevoMapper { case EmailTemplate.SUPPRIMER_CLASSE_ENGAGEE: case EmailTemplate.NOUVELLE_CLASSE_ENGAGEE: return this.mapSupprimerClasseEngagee(template, emailParams as SupprimerClasseEngageeParams); + case EmailTemplate.JEUNE_CHANGE_SESSION_TO_CLE: + case EmailTemplate.JEUNE_CHANGE_SESSION_CLE_TO_HTS: + return this.mapJeuneBasculeCLE(template, emailParams as jeuneBasculeCLEParams); + case EmailTemplate.PARENT_JEUNE_SESSION_CHANGE: + return this.mapJeuneBasculeParentNotif(template, emailParams as jeuneBasculeParentNotifParams); + case EmailTemplate.CHANGE_SESSION: + return this.mapJeuneBasculeNotifToJeune(template, emailParams as jeuneBasculeNotifToJeune); } } @@ -112,6 +122,57 @@ export class EmailBrevoMapper { templateId: Number(template), }; } + + static mapJeuneBasculeCLE( + template: EmailTemplate, + jeuneBasculeCLEParams: jeuneBasculeCLEParams, + ): EmailProviderJeuneBasculeCLE { + return { + to: jeuneBasculeCLEParams.to, + params: { + firstname: jeuneBasculeCLEParams.firstname, + name: jeuneBasculeCLEParams.name, + class_name: jeuneBasculeCLEParams.class_name, + class_code: jeuneBasculeCLEParams.class_code, + cta: jeuneBasculeCLEParams.cta, + }, + templateId: Number(template), + }; + } + + static mapJeuneBasculeParentNotif( + template: EmailTemplate, + jeuneBasculeParentNotifParams: jeuneBasculeParentNotifParams, + ): EmailProviderJeuneBasculeParentNotif { + return { + to: jeuneBasculeParentNotifParams.to, + params: { + cohort: jeuneBasculeParentNotifParams.cohort, + youngFirstName: jeuneBasculeParentNotifParams.youngFirstName, + youngName: jeuneBasculeParentNotifParams.youngName, + cta: jeuneBasculeParentNotifParams.cta, + }, + templateId: Number(template), + }; + } + + static mapJeuneBasculeNotifToJeune( + template: EmailTemplate, + jeuneBasculeNotifToJeune: jeuneBasculeNotifToJeune, + ): EmailProviderJeuneBasculeNotifToJeune { + return { + to: jeuneBasculeNotifToJeune.to, + params: { + motif: jeuneBasculeNotifToJeune.motif, + message: jeuneBasculeNotifToJeune.message, + newcohortdate: jeuneBasculeNotifToJeune.newcohortdate, + oldprogram: jeuneBasculeNotifToJeune.oldprogram, + newprogram: jeuneBasculeNotifToJeune.newprogram, + cta: jeuneBasculeNotifToJeune.cta, + }, + templateId: Number(template), + }; + } } export interface EmailProviderVerifierClasseAdminCle extends EmailProviderParams { @@ -151,3 +212,33 @@ export interface EmailProviderSupprimerClasseEngagee extends EmailProviderParams cta: string; }; } + +export interface EmailProviderJeuneBasculeCLE extends EmailProviderParams { + params: { + firstname: string; + name: string; + class_name: string; + class_code: string; + cta: string; + }; +} + +export interface EmailProviderJeuneBasculeParentNotif extends EmailProviderParams { + params: { + cohort: string; + youngFirstName: string; + youngName: string; + cta: string; + }; +} + +export interface EmailProviderJeuneBasculeNotifToJeune extends EmailProviderParams { + params: { + motif: string; + message: string; + newcohortdate: string; + oldprogram: string; + newprogram: string; + cta: string; + }; +} diff --git a/packages/lib/src/constants/inscription.ts b/packages/lib/src/constants/inscription.ts new file mode 100644 index 0000000000..59f32d8e14 --- /dev/null +++ b/packages/lib/src/constants/inscription.ts @@ -0,0 +1,10 @@ +export enum STEPS2023 { + EMAIL_WAITING_VALIDATION = "EMAIL_WAITING_VALIDATION", + COORDONNEES = "COORDONNEES", + CONSENTEMENTS = "CONSENTEMENTS", + REPRESENTANTS = "REPRESENTANTS", + DOCUMENTS = "DOCUMENTS", + CONFIRM = "CONFIRM", + WAITING_CONSENT = "WAITING_CONSENT", + DONE = "DONE", +} diff --git a/packages/lib/src/dto/youngDto.ts b/packages/lib/src/dto/youngDto.ts index 5476921f7e..273a11c50f 100644 --- a/packages/lib/src/dto/youngDto.ts +++ b/packages/lib/src/dto/youngDto.ts @@ -201,6 +201,7 @@ export interface YoungDto { parent2AllowImageRights?: string; parent2AllowImageRightsReset?: string; parent2ContactPreference?: string; + cohesionStayMedicalFileReceived?: string; hostLastName?: string; hostFirstName?: string; hostRelationship?: string; @@ -285,6 +286,7 @@ export interface YoungDto { militaryPreparationFilesCertificate?: string[]; statusMilitaryPreparationFiles?: string; militaryPreparationCorrectionMessage?: string; + cniFiles?: string[]; files?: { cniFiles?: File[]; highSkilledActivityProofFiles?: File[];