Skip to content

Commit

Permalink
assessment creation email to agency validators and counsellors for im…
Browse files Browse the repository at this point in the history
…mersion kind only
  • Loading branch information
bbohec committed Jan 15, 2025
1 parent 0ade207 commit 6fa3679
Show file tree
Hide file tree
Showing 13 changed files with 768 additions and 345 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { ColumnDefinitions, MigrationBuilder } from "node-pg-migrate";

export const shorthands: ColumnDefinitions | undefined = undefined;

export async function up(pgm: MigrationBuilder): Promise<void> {
pgm.sql(`
UPDATE notifications_email
SET email_kind = 'ASSESSMENT_BENEFICIARY_NOTIFICATION'
WHERE email_kind = 'BENEFICIARY_ASSESSMENT_NOTIFICATION'
`);
pgm.sql(`
UPDATE notifications_email
SET email_kind = 'ASSESSMENT_ESTABLISHMENT_NOTIFICATION'
WHERE email_kind = 'ESTABLISHMENT_ASSESSMENT_NOTIFICATION'
`);
}

export async function down(pgm: MigrationBuilder): Promise<void> {
pgm.sql(`
UPDATE notifications_email
SET email_kind = 'BENEFICIARY_ASSESSMENT_NOTIFICATION'
WHERE email_kind = 'ASSESSMENT_BENEFICIARY_NOTIFICATION'
`);
pgm.sql(`
UPDATE notifications_email
SET email_kind = 'ESTABLISHMENT_ASSESSMENT_NOTIFICATION'
WHERE email_kind = 'ASSESSMENT_ESTABLISHMENT_NOTIFICATION'
`);
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ describe("Pg implementation of ConventionQueries", () => {
createdAt: Date;
convention: ConventionDto;
emailKind:
| "ESTABLISHMENT_ASSESSMENT_NOTIFICATION"
| "ASSESSMENT_ESTABLISHMENT_NOTIFICATION"
| "VALIDATED_CONVENTION_FINAL_CONFIRMATION";
}): EmailNotification => {
return emailKind === "ESTABLISHMENT_ASSESSMENT_NOTIFICATION"
return emailKind === "ASSESSMENT_ESTABLISHMENT_NOTIFICATION"
? {
createdAt: createdAt.toISOString(),
followedIds: {
Expand All @@ -65,7 +65,7 @@ describe("Pg implementation of ConventionQueries", () => {
id,
kind: "email",
templatedContent: {
kind: "ESTABLISHMENT_ASSESSMENT_NOTIFICATION",
kind: "ASSESSMENT_ESTABLISHMENT_NOTIFICATION",
params: {
internshipKind: "immersion",
assessmentCreationLink: "fake-link",
Expand Down Expand Up @@ -742,7 +742,7 @@ describe("Pg implementation of ConventionQueries", () => {
createdAt: subDays(new Date(dateEnd15), 1),
convention:
validatedImmersionEndingThe15thThatAlreadyReceivedAnAssessmentEmail,
emailKind: "ESTABLISHMENT_ASSESSMENT_NOTIFICATION",
emailKind: "ASSESSMENT_ESTABLISHMENT_NOTIFICATION",
});
const conventionValidateEndingThe14thNotification: Notification =
createNotification({
Expand Down Expand Up @@ -810,7 +810,7 @@ describe("Pg implementation of ConventionQueries", () => {
from: date,
to: addHours(date, 24),
},
"ESTABLISHMENT_ASSESSMENT_NOTIFICATION",
"ASSESSMENT_ESTABLISHMENT_NOTIFICATION",
);

// Assert
Expand Down Expand Up @@ -860,7 +860,7 @@ describe("Pg implementation of ConventionQueries", () => {
from: subDays(validationDate, 5),
to: addHours(validationDate, 24),
},
"ESTABLISHMENT_ASSESSMENT_NOTIFICATION",
"ASSESSMENT_ESTABLISHMENT_NOTIFICATION",
);

expectArraysToEqualIgnoringOrder(queryResults, [
Expand Down Expand Up @@ -896,7 +896,7 @@ describe("Pg implementation of ConventionQueries", () => {
from: tomorrow,
to: addHours(tomorrow, 24),
},
"ESTABLISHMENT_ASSESSMENT_NOTIFICATION",
"ASSESSMENT_ESTABLISHMENT_NOTIFICATION",
);

expectArraysToEqualIgnoringOrder(queryResults, [pastConvention]);
Expand Down
4 changes: 2 additions & 2 deletions back/src/domains/convention/ports/ConventionQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ export type GetConventionsFilters = {

export type AssessmentEmailKind = ExtractFromExisting<
TemplatedEmail["kind"],
| "ESTABLISHMENT_ASSESSMENT_NOTIFICATION"
| "BENEFICIARY_ASSESSMENT_NOTIFICATION"
| "ASSESSMENT_ESTABLISHMENT_NOTIFICATION"
| "ASSESSMENT_BENEFICIARY_NOTIFICATION"
>;

export type GetConventionsSortBy = keyof Pick<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class SendBeneficiariesPdfAssessmentsEmails extends TransactionalUseCase<
const conventions =
await uow.conventionQueries.getAllConventionsForThoseEndingThatDidntGoThrough(
params.conventionEndDate,
"BENEFICIARY_ASSESSMENT_NOTIFICATION",
"ASSESSMENT_BENEFICIARY_NOTIFICATION",
);
const errors: Record<ConventionId, Error> = {};
await Promise.all(
Expand Down Expand Up @@ -97,7 +97,7 @@ export class SendBeneficiariesPdfAssessmentsEmails extends TransactionalUseCase<
await this.#saveNotificationAndRelatedEvent(uow, {
kind: "email",
templatedContent: {
kind: "BENEFICIARY_ASSESSMENT_NOTIFICATION",
kind: "ASSESSMENT_BENEFICIARY_NOTIFICATION",
recipients: [convention.signatories.beneficiary.email],
sender: immersionFacileNoReplyEmailSender,
params: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ describe("SendBeneficiariesPdfAssessmentsEmails", () => {
expectSavedNotificationsAndEvents({
emails: [
{
kind: "BENEFICIARY_ASSESSMENT_NOTIFICATION",
kind: "ASSESSMENT_BENEFICIARY_NOTIFICATION",
params: {
conventionId: conventionEndingTomorrow.id,
beneficiaryLastName:
Expand Down Expand Up @@ -138,7 +138,7 @@ describe("SendBeneficiariesPdfAssessmentsEmails", () => {
const signatories = conventionEndingTomorrow.signatories;

const email: TemplatedEmail = {
kind: "BENEFICIARY_ASSESSMENT_NOTIFICATION",
kind: "ASSESSMENT_BENEFICIARY_NOTIFICATION",
params: {
internshipKind: "immersion",
beneficiaryFirstName: signatories.beneficiary.firstName,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import {
AgencyRole,
AgencyWithUsersRights,
ConventionDto,
ConventionId,
DateRange,
Email,
castError,
frontRoutes,
immersionFacileNoReplyEmailSender,
withDateRangeSchema,
} from "shared";
import { z } from "zod";
import { GenerateConventionMagicLinkUrl } from "../../../config/bootstrap/magicLinkUrl";
import { getAgencyEmailsByRole } from "../../../utils/agency";
import { createLogger } from "../../../utils/logger";
import { TransactionalUseCase } from "../../core/UseCase";
import { CreateNewEvent } from "../../core/events/ports/EventBus";
import { SaveNotificationAndRelatedEvent } from "../../core/notifications/helpers/Notification";
import {
NotificationContentAndFollowedIds,
SaveNotificationAndRelatedEvent,
} from "../../core/notifications/helpers/Notification";
import { TimeGateway } from "../../core/time-gateway/ports/TimeGateway";
import { UnitOfWork } from "../../core/unit-of-work/ports/UnitOfWork";
import { UnitOfWorkPerformer } from "../../core/unit-of-work/ports/UnitOfWorkPerformer";
Expand Down Expand Up @@ -67,7 +74,7 @@ export class SendEmailsWithAssessmentCreationLink extends TransactionalUseCase<
const conventions =
await uow.conventionQueries.getAllConventionsForThoseEndingThatDidntGoThrough(
params.conventionEndDate,
"ESTABLISHMENT_ASSESSMENT_NOTIFICATION",
"ASSESSMENT_ESTABLISHMENT_NOTIFICATION",
);

logger.info({
Expand All @@ -80,12 +87,11 @@ export class SendEmailsWithAssessmentCreationLink extends TransactionalUseCase<
const errors: Record<ConventionId, Error> = {};
await Promise.all(
conventions.map(async (convention) => {
await this.#sendOneEmailWithAssessmentCreationLink(
uow,
convention,
).catch((error) => {
errors[convention.id] = castError(error);
});
await this.#sendEmailsWithAssessmentCreationLink(uow, convention).catch(
(error) => {
errors[convention.id] = castError(error);
},
);
}),
);

Expand All @@ -95,18 +101,112 @@ export class SendEmailsWithAssessmentCreationLink extends TransactionalUseCase<
};
}

async #sendOneEmailWithAssessmentCreationLink(
async #sendEmailsWithAssessmentCreationLink(
uow: UnitOfWork,
convention: ConventionDto,
) {
const [agency] = await uow.agencyRepository.getByIds([convention.agencyId]);
if (!agency)
throw new Error(`Missing agency ${convention.agencyId} on repository.`);

await this.#saveNotificationAndRelatedEvent(uow, {
await this.#saveNotificationAndRelatedEvent(
uow,
this.#makeEstablishmentAssessmentEmail(convention, agency),
);

if (convention.internshipKind === "immersion")
await this.onImmersionConvention(uow, convention, agency);

await uow.outboxRepository.save(
this.#createNewEvent({
topic: "EmailWithLinkToCreateAssessmentSent",
payload: { id: convention.id },
}),
);
}

private async onImmersionConvention(
uow: UnitOfWork,
convention: ConventionDto,
agency: AgencyWithUsersRights,
) {
for (const validatorEmail of await getAgencyEmailsByRole({
agency,
role: "validator",
uow,
})) {
await this.#saveNotificationAndRelatedEvent(
uow,
await this.#makeAgencyAssessmentEmail(
convention,
agency,
validatorEmail,
"validator",
),
);
}

for (const counsellorEmail of await getAgencyEmailsByRole({
agency,
role: "counsellor",
uow,
})) {
await this.#saveNotificationAndRelatedEvent(
uow,
await this.#makeAgencyAssessmentEmail(
convention,
agency,
counsellorEmail,
"counsellor",
),
);
}
}

#makeAgencyAssessmentEmail(
convention: ConventionDto,
agency: AgencyWithUsersRights,
email: Email,
role: AgencyRole,
): NotificationContentAndFollowedIds {
return {
followedIds: {
agencyId: convention.agencyId,
conventionId: convention.id,
establishmentSiret: convention.siret,
},
kind: "email",
templatedContent: {
kind: "ESTABLISHMENT_ASSESSMENT_NOTIFICATION",
kind: "ASSESSMENT_AGENCY_NOTIFICATION",
params: {
beneficiaryFirstName: convention.signatories.beneficiary.firstName,
beneficiaryLastName: convention.signatories.beneficiary.lastName,
conventionId: convention.id,
internshipKind: convention.internshipKind,
businessName: convention.businessName,
agencyLogoUrl: agency.logoUrl ?? undefined,
assessmentCreationLink: this.#generateConventionMagicLinkUrl({
id: convention.id,
email,
role,
targetRoute: frontRoutes.assessment,
now: this.#timeGateway.now(),
}),
},
recipients: [email],
sender: immersionFacileNoReplyEmailSender,
},
};
}

#makeEstablishmentAssessmentEmail(
convention: ConventionDto,
agency: AgencyWithUsersRights,
): NotificationContentAndFollowedIds {
return {
kind: "email",
templatedContent: {
kind: "ASSESSMENT_ESTABLISHMENT_NOTIFICATION",
recipients: [convention.establishmentTutor.email],
sender: immersionFacileNoReplyEmailSender,
params: {
Expand All @@ -130,13 +230,6 @@ export class SendEmailsWithAssessmentCreationLink extends TransactionalUseCase<
agencyId: convention.agencyId,
establishmentSiret: convention.siret,
},
});

await uow.outboxRepository.save(
this.#createNewEvent({
topic: "EmailWithLinkToCreateAssessmentSent",
payload: { id: convention.id },
}),
);
};
}
}
Loading

0 comments on commit 6fa3679

Please sign in to comment.