diff --git a/sources/packages/backend/apps/queue-consumers/src/processors/schedulers/esdc-integration/ecert-integration/_tests_/ecert-full-time-process-integration.scheduler.e2e-spec.ts b/sources/packages/backend/apps/queue-consumers/src/processors/schedulers/esdc-integration/ecert-integration/_tests_/ecert-full-time-process-integration.scheduler.e2e-spec.ts index e4bcb6a217..091c9570ae 100644 --- a/sources/packages/backend/apps/queue-consumers/src/processors/schedulers/esdc-integration/ecert-integration/_tests_/ecert-full-time-process-integration.scheduler.e2e-spec.ts +++ b/sources/packages/backend/apps/queue-consumers/src/processors/schedulers/esdc-integration/ecert-integration/_tests_/ecert-full-time-process-integration.scheduler.e2e-spec.ts @@ -8,6 +8,7 @@ import { DisbursementScheduleStatus, DisbursementValueType, FormYesNoOptions, + NotificationMessage, NotificationMessageType, OfferingIntensity, RelationshipStatus, @@ -22,6 +23,7 @@ import { createFakeDisbursementOveraward, createFakeDisbursementValue, createFakeMSFAANumber, + createFakeNotification, createFakeUser, saveFakeApplicationDisbursements, saveFakeApplicationRestrictionBypass, @@ -1361,8 +1363,8 @@ describe( expect( mockedJob.containLogMessages([ "Disbursement estimated awards do not contain any amount to be disbursed.", - `Creating notifications for disbursement id: ${disbursement.id} for student and ministry.`, - `Completed creating notifications for disbursement id: ${disbursement.id} for student and ministry.`, + `Ministry Blocked Disbursement notification created for disbursement ID ${disbursement.id}.`, + `Student Blocked Disbursement notification created for disbursement ID ${disbursement.id}.`, ]), ).toBe(true); const notifications = await db.notification.find({ @@ -1399,6 +1401,77 @@ describe( }, ); + it("Should create a notification for the student and avoid creating a notification for the Ministry when the Ministry was already notified about the same blocked disbursement.", async () => { + // Arrange + const { student, disbursement } = await createBlockedDisbursementTestData( + db, + { + offeringIntensity: OfferingIntensity.fullTime, + isValidSIN: true, + disbursementValues: [], + }, + ); + // Create a sent notification for Ministry. + const ministryNotification = createFakeNotification( + { + user: systemUsersService.systemUser, + auditUser: systemUsersService.systemUser, + notificationMessage: { + id: NotificationMessageType.MinistryNotificationDisbursementBlocked, + } as NotificationMessage, + }, + { + initialValue: { + metadata: { + disbursementId: disbursement.id, + }, + dateSent: new Date(), + }, + }, + ); + await db.notification.save(ministryNotification); + + // Queued job. + const mockedJob = mockBullJob(); + + // Act + await processor.processQueue(mockedJob.job); + + // Assert + // Assert disbursement was blocked and expected student notification was created and ministry notification was not created. + expect( + mockedJob.containLogMessages([ + "The step determined that the calculation should be interrupted. This disbursement will not be part of the next e-Cert generation.", + `Ministry Blocked Disbursement notification should not be created at this moment for disbursement ID ${disbursement.id}.`, + `Student Blocked Disbursement notification created for disbursement ID ${disbursement.id}.`, + ]), + ).toBe(true); + // Assert only student notification was created on DB. + const notifications = await db.notification.find({ + select: { + id: true, + user: { id: true }, + notificationMessage: { id: true }, + }, + relations: { user: true, notificationMessage: true }, + where: { + metadata: { + disbursementId: disbursement.id, + }, + dateSent: IsNull(), + }, + }); + expect(notifications).toEqual([ + { + id: expect.any(Number), + notificationMessage: { + id: NotificationMessageType.StudentNotificationDisbursementBlocked, + }, + user: { id: student.user.id }, + }, + ]); + }); + /** * Helper function to get the uploaded file name. * @returns The uploaded file name diff --git a/sources/packages/backend/apps/queue-consumers/src/processors/schedulers/esdc-integration/ecert-integration/_tests_/ecert-part-time-process-integration.scheduler.e2e-spec.ts b/sources/packages/backend/apps/queue-consumers/src/processors/schedulers/esdc-integration/ecert-integration/_tests_/ecert-part-time-process-integration.scheduler.e2e-spec.ts index c8ac24ee7d..4a46e4fac0 100644 --- a/sources/packages/backend/apps/queue-consumers/src/processors/schedulers/esdc-integration/ecert-integration/_tests_/ecert-part-time-process-integration.scheduler.e2e-spec.ts +++ b/sources/packages/backend/apps/queue-consumers/src/processors/schedulers/esdc-integration/ecert-integration/_tests_/ecert-part-time-process-integration.scheduler.e2e-spec.ts @@ -126,8 +126,8 @@ describe( ]); expect( mockedJob.containLogMessages([ - `Creating notifications for disbursement id: ${disbursement.id} for student and ministry.`, - `Completed creating notifications for disbursement id: ${disbursement.id} for student and ministry.`, + `Ministry Blocked Disbursement notification created for disbursement ID ${disbursement.id}.`, + `Student Blocked Disbursement notification created for disbursement ID ${disbursement.id}.`, ]), ).toBe(true); const notifications = await db.notification.find({ @@ -191,8 +191,8 @@ describe( expect( mockedJob.containLogMessages([ "Disbursement estimated awards do not contain any amount to be disbursed.", - `Creating notifications for disbursement id: ${disbursement.id} for student and ministry.`, - `Completed creating notifications for disbursement id: ${disbursement.id} for student and ministry.`, + `Ministry Blocked Disbursement notification created for disbursement ID ${disbursement.id}.`, + `Student Blocked Disbursement notification created for disbursement ID ${disbursement.id}.`, ]), ).toBe(true); const notifications = await db.notification.find({ @@ -287,6 +287,13 @@ describe( `Generated file: ${uploadedFileName}`, "Uploaded records: 0", ]); + expect( + mockedJob.containLogMessages([ + "The step determined that the calculation should be interrupted. This disbursement will not be part of the next e-Cert generation.", + `Ministry Blocked Disbursement notification should not be created at this moment for disbursement ID ${disbursement.id}.`, + `Student Blocked Disbursement notification should not be created at this moment for disbursement ID ${disbursement.id}.`, + ]), + ).toBe(true); const notificationsCount = await db.notification.count({ where: { notificationMessage: { @@ -326,8 +333,8 @@ describe( ]); expect( mockedJob.containLogMessages([ - `Creating notifications for disbursement id: ${disbursement.id} for student and ministry.`, - `Completed creating notifications for disbursement id: ${disbursement.id} for student and ministry.`, + `Ministry Blocked Disbursement notification should not be created at this moment for disbursement ID ${disbursement.id}.`, + `Student Blocked Disbursement notification created for disbursement ID ${disbursement.id}.`, ]), ).toBe(true); const notificationsCount = await db.notification.count({ @@ -338,8 +345,8 @@ describe( dateSent: IsNull(), }, }); - // Checking 1 created notification for the student and 1 notification for the ministry. - expect(notificationsCount).toBe(2); + // Checking 1 created notification for the student only. + expect(notificationsCount).toBe(1); }); it("Should create an e-Cert with one disbursement record for one student with one eligible schedule.", async () => { diff --git a/sources/packages/backend/libs/integrations/src/esdc-integration/e-cert-integration/e-cert-integration.module.ts b/sources/packages/backend/libs/integrations/src/esdc-integration/e-cert-integration/e-cert-integration.module.ts index 29783b5a35..07e368217a 100644 --- a/sources/packages/backend/libs/integrations/src/esdc-integration/e-cert-integration/e-cert-integration.module.ts +++ b/sources/packages/backend/libs/integrations/src/esdc-integration/e-cert-integration/e-cert-integration.module.ts @@ -46,6 +46,10 @@ import { } from "@sims/integrations/services/disbursement-schedule/e-cert-calculation"; import { FullTimeECertFileHandler } from "./full-time-e-cert-file-handler"; import { PartTimeECertFileHandler } from "./part-time-e-cert-file-handler"; +import { + MinistryBlockedDisbursementNotification, + StudentBlockedDisbursementNotification, +} from "@sims/integrations/services/disbursement-schedule/e-cert-notification"; @Module({ imports: [ConfigModule, SystemUserModule], @@ -88,6 +92,8 @@ import { PartTimeECertFileHandler } from "./part-time-e-cert-file-handler"; StudentLoanBalanceSharedService, ECertFeedbackErrorService, ECertPreValidationService, + MinistryBlockedDisbursementNotification, + StudentBlockedDisbursementNotification, ], exports: [ FullTimeECertFileHandler, diff --git a/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-calculation/e-cert-calculation-process.ts b/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-calculation/e-cert-calculation-process.ts index f350d292ed..5187107390 100644 --- a/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-calculation/e-cert-calculation-process.ts +++ b/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-calculation/e-cert-calculation-process.ts @@ -123,8 +123,8 @@ export abstract class ECertCalculationProcess { disbursementLog, ); if (!shouldProceed) { - await this.eCertNotificationService.createDisbursementBlockedNotification( - eCertDisbursement.disbursement.id, + await this.eCertNotificationService.notifyBlockedDisbursement( + eCertDisbursement, entityManager, parentLog, ); diff --git a/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-notification/blocked-disbursement/ministry-blocked-disbursement-notification.ts b/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-notification/blocked-disbursement/ministry-blocked-disbursement-notification.ts new file mode 100644 index 0000000000..30a372ee40 --- /dev/null +++ b/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-notification/blocked-disbursement/ministry-blocked-disbursement-notification.ts @@ -0,0 +1,85 @@ +import { Injectable } from "@nestjs/common"; +import { + DisbursementBlockedNotification, + NotificationActionsService, +} from "@sims/services"; +import { Notification, NotificationMessageType, Student } from "@sims/sims-db"; +import { EntityManager } from "typeorm"; +import { ECertNotification } from "../e-cert-notification"; +import { EligibleECertDisbursement } from "../../disbursement-schedule.models"; + +/** + * Creates a notification for a blocked disbursement for the Ministry, if required. + */ +@Injectable() +export class MinistryBlockedDisbursementNotification extends ECertNotification { + constructor( + private readonly notificationActionsService: NotificationActionsService, + ) { + super("Ministry Blocked Disbursement"); + } + + /** + * Determines whether a notification should be created or not. + * @param eCertDisbursement eligible disbursement to be potentially added to an e-Cert. + * @param entityManager entity manager to execute in transaction. + * @returns true if a notification should be created, false otherwise. + */ + protected async shouldCreateNotification( + eCertDisbursement: EligibleECertDisbursement, + entityManager: EntityManager, + ): Promise { + const hasNotification = await entityManager + .getRepository(Notification) + .exists({ + where: { + notificationMessage: { + id: NotificationMessageType.MinistryNotificationDisbursementBlocked, + }, + metadata: { + disbursementId: eCertDisbursement.disbursement.id, + }, + }, + }); + return !hasNotification; + } + + /** + * Creates a notification for the given e-Cert disbursement. + * @param eCertDisbursement eligible disbursement to be potentially added to an e-Cert. + * @param entityManager entity manager to execute in transaction. + */ + protected async createNotification( + eCertDisbursement: EligibleECertDisbursement, + entityManager: EntityManager, + ): Promise { + const student = await entityManager.getRepository(Student).findOne({ + select: { + id: true, + birthDate: true, + user: { + id: true, + firstName: true, + lastName: true, + email: true, + }, + }, + relations: { + user: true, + }, + where: { id: eCertDisbursement.studentId }, + }); + const ministryNotification: DisbursementBlockedNotification = { + givenNames: student.user.firstName, + lastName: student.user.lastName, + email: student.user.email, + birthDate: student.birthDate, + applicationNumber: eCertDisbursement.applicationNumber, + }; + await this.notificationActionsService.saveDisbursementBlockedNotificationForMinistry( + ministryNotification, + eCertDisbursement.disbursement.id, + entityManager, + ); + } +} diff --git a/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-notification/blocked-disbursement/student-blocked-disbursement-notification.ts b/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-notification/blocked-disbursement/student-blocked-disbursement-notification.ts new file mode 100644 index 0000000000..d9de033b7e --- /dev/null +++ b/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-notification/blocked-disbursement/student-blocked-disbursement-notification.ts @@ -0,0 +1,105 @@ +import { Injectable } from "@nestjs/common"; +import { + NotificationActionsService, + StudentNotification, +} from "@sims/services"; +import { + BLOCKED_DISBURSEMENT_MAXIMUM_NOTIFICATIONS_TO_SEND, + BLOCKED_DISBURSEMENT_NOTIFICATION_MIN_DAYS_INTERVAL, +} from "@sims/services/constants"; +import { Notification, NotificationMessageType, Student } from "@sims/sims-db"; +import { dateDifference } from "@sims/utilities"; +import { EntityManager } from "typeorm"; +import { ECertNotification } from "../e-cert-notification"; +import { EligibleECertDisbursement } from "../../disbursement-schedule.models"; + +interface NotificationData { + maxCreatedAt: Date; + notificationCount: number; +} + +/** + * Creates a notification for a blocked disbursement for the Student, if required. + */ +@Injectable() +export class StudentBlockedDisbursementNotification extends ECertNotification { + constructor( + private readonly notificationActionsService: NotificationActionsService, + ) { + super("Student Blocked Disbursement"); + } + + /** + * Determines whether a notification should be created or not. + * @param eCertDisbursement eligible disbursement to be potentially added to an e-Cert. + * @param entityManager entity manager to execute in transaction. + * @returns true if a notification should be created, false otherwise. + */ + protected async shouldCreateNotification( + eCertDisbursement: EligibleECertDisbursement, + entityManager: EntityManager, + ): Promise { + const notification = await entityManager + .getRepository(Notification) + .createQueryBuilder("notification") + .select("count(*)::int", "notificationCount") + .addSelect("max(notification.createdAt)", "maxCreatedAt") + .innerJoin("notification.notificationMessage", "notificationMessage") + .where("notificationMessage.id = :notificationMessageId", { + notificationMessageId: + NotificationMessageType.StudentNotificationDisbursementBlocked, + }) + .andWhere("notification.metadata->>'disbursementId' = :disbursementId", { + disbursementId: eCertDisbursement.disbursement.id, + }) + .getRawOne(); + const canSendNewNotification = + dateDifference(new Date(), notification.maxCreatedAt) > + BLOCKED_DISBURSEMENT_NOTIFICATION_MIN_DAYS_INTERVAL; + // Condition check to create notifications: Less than BLOCKED_DISBURSEMENT_MAXIMUM_NOTIFICATIONS_TO_SEND notifications are created previously and there are no failures in sending those created notifications. + // Plus, it has been at least BLOCKED_DISBURSEMENT_NOTIFICATION_MIN_DAYS_INTERVAL days from the last created notification for this disbursement. + return ( + !notification.notificationCount || + (notification.notificationCount < + BLOCKED_DISBURSEMENT_MAXIMUM_NOTIFICATIONS_TO_SEND && + canSendNewNotification) + ); + } + + /** + * Creates a notification for the given e-Cert disbursement. + * @param eCertDisbursement eligible disbursement to be potentially added to an e-Cert. + * @param entityManager entity manager to execute in transaction. + */ + protected async createNotification( + eCertDisbursement: EligibleECertDisbursement, + entityManager: EntityManager, + ): Promise { + const student = await entityManager.getRepository(Student).findOne({ + select: { + id: true, + user: { + id: true, + firstName: true, + lastName: true, + email: true, + }, + }, + relations: { + user: true, + }, + where: { id: eCertDisbursement.studentId }, + }); + const studentNotification: StudentNotification = { + givenNames: student.user.firstName, + lastName: student.user.lastName, + toAddress: student.user.email, + userId: student.user.id, + }; + await this.notificationActionsService.saveDisbursementBlockedNotificationForStudent( + studentNotification, + eCertDisbursement.disbursement.id, + entityManager, + ); + } +} diff --git a/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-notification/e-cert-notification.service.ts b/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-notification/e-cert-notification.service.ts index 8187c6050d..a1b5df2b8c 100644 --- a/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-notification/e-cert-notification.service.ts +++ b/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-notification/e-cert-notification.service.ts @@ -1,169 +1,36 @@ import { Injectable } from "@nestjs/common"; -import { - DisbursementBlockedNotification, - NotificationActionsService, - StudentNotification, -} from "@sims/services"; -import { - BLOCKED_DISBURSEMENT_MAXIMUM_NOTIFICATIONS_TO_SEND, - BLOCKED_DISBURSEMENT_NOTIFICATION_MIN_DAYS_INTERVAL, -} from "@sims/services/constants"; -import { - DisbursementSchedule, - Notification, - NotificationMessageType, -} from "@sims/sims-db"; -import { dateDifference } from "@sims/utilities"; import { ProcessSummary } from "@sims/utilities/logger"; import { EntityManager } from "typeorm"; - -interface NotificationData { - maxCreatedAt: Date; - notificationCount: number; -} +import { EligibleECertDisbursement } from "../disbursement-schedule.models"; +import { + MinistryBlockedDisbursementNotification, + StudentBlockedDisbursementNotification, +} from "."; @Injectable() export class ECertNotificationService { constructor( - private readonly notificationActionsService: NotificationActionsService, + private readonly ministryBlockedDisbursementNotification: MinistryBlockedDisbursementNotification, + private readonly studentBlockedDisbursementNotification: StudentBlockedDisbursementNotification, ) {} /** - * Checks and creates disbursement blocked notification. - * @param disbursementId disbursement id. + * Checks and creates disbursement blocked notification(s). + * @param eCertDisbursement eligible disbursement to be potentially added to an e-Cert. * @param entityManager entity manager to execute in transaction. - * @param parentLog cumulative process log. + * @param log cumulative log summary. */ - async createDisbursementBlockedNotification( - disbursementId: number, + async notifyBlockedDisbursement( + eCertDisbursement: EligibleECertDisbursement, entityManager: EntityManager, - parentLog: ProcessSummary, + log: ProcessSummary, ): Promise { - const shouldCreateNotification = - await this.shouldCreateDisbursementBlockedNotification( - disbursementId, - entityManager, - ); - if (shouldCreateNotification) { - const notificationLog = new ProcessSummary(); - parentLog.children(notificationLog); - notificationLog.info( - `Creating notifications for disbursement id: ${disbursementId} for student and ministry.`, - ); - await this.createDisbursementBlockedNotifications( - disbursementId, - entityManager, - ); - notificationLog.info( - `Completed creating notifications for disbursement id: ${disbursementId} for student and ministry.`, - ); - } - } - - /** - * Checks whether the disbursement blocked notification should be created or not. - * @param disbursementId disbursement id. - * @param entityManager entity manager to execute in transaction. - * @returns boolean indicating if the disbursement blocked notification should be created or not. - */ - private async shouldCreateDisbursementBlockedNotification( - disbursementId: number, - entityManager: EntityManager, - ): Promise { - const notification = await entityManager - .getRepository(Notification) - .createQueryBuilder("notification") - .select("count(*)::int", "notificationCount") - .addSelect("max(notification.createdAt)", "maxCreatedAt") - .innerJoin("notification.notificationMessage", "notificationMessage") - .where("notificationMessage.id = :notificationMessageId", { - notificationMessageId: - NotificationMessageType.StudentNotificationDisbursementBlocked, - }) - .andWhere("notification.metadata->>'disbursementId' = :disbursementId", { - disbursementId, - }) - .getRawOne(); - const canSendNewNotification = - dateDifference(new Date(), notification.maxCreatedAt) > - BLOCKED_DISBURSEMENT_NOTIFICATION_MIN_DAYS_INTERVAL; - // Condition check to create notifications: Less than BLOCKED_DISBURSEMENT_MAXIMUM_NOTIFICATIONS_TO_SEND notifications are created previously and there are no failures in sending those created notifications. - // Plus, it has been at least BLOCKED_DISBURSEMENT_NOTIFICATION_MIN_DAYS_INTERVAL days from the last created notification for this disbursement. - return ( - !notification.notificationCount || - (notification.notificationCount < - BLOCKED_DISBURSEMENT_MAXIMUM_NOTIFICATIONS_TO_SEND && - canSendNewNotification) + const notifications = [ + this.ministryBlockedDisbursementNotification, + this.studentBlockedDisbursementNotification, + ].map((notification) => + notification.notify(eCertDisbursement, entityManager, log), ); - } - - /** - * Creates disbursement blocked notifications for student and ministry. - * @param disbursementId disbursement id associated with the blocked disbursement. - * @param entityManager entity manager to execute in transaction. - */ - private async createDisbursementBlockedNotifications( - disbursementId: number, - entityManager: EntityManager, - ): Promise { - const disbursement = await entityManager - .getRepository(DisbursementSchedule) - .findOne({ - select: { - id: true, - studentAssessment: { - id: true, - application: { - id: true, - applicationNumber: true, - student: { - id: true, - birthDate: true, - user: { - id: true, - firstName: true, - lastName: true, - email: true, - }, - }, - }, - }, - }, - relations: { - studentAssessment: { application: { student: { user: true } } }, - }, - where: { id: disbursementId }, - }); - const student = disbursement.studentAssessment.application.student; - const studentNotification: StudentNotification = { - givenNames: student.user.firstName, - lastName: student.user.lastName, - toAddress: student.user.email, - userId: student.user.id, - }; - const ministryNotification: DisbursementBlockedNotification = { - givenNames: student.user.firstName, - lastName: student.user.lastName, - email: student.user.email, - birthDate: student.birthDate, - applicationNumber: - disbursement.studentAssessment.application.applicationNumber, - }; - const disbursementBlockedNotificationForStudentPromise = - this.notificationActionsService.saveDisbursementBlockedNotificationForStudent( - studentNotification, - disbursementId, - entityManager, - ); - const disbursementBlockedNotificationForMinistryPromise = - this.notificationActionsService.saveDisbursementBlockedNotificationForMinistry( - ministryNotification, - disbursementId, - entityManager, - ); - await Promise.all([ - disbursementBlockedNotificationForStudentPromise, - disbursementBlockedNotificationForMinistryPromise, - ]); + await Promise.all(notifications); } } diff --git a/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-notification/e-cert-notification.ts b/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-notification/e-cert-notification.ts new file mode 100644 index 0000000000..680f9a4cc8 --- /dev/null +++ b/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-notification/e-cert-notification.ts @@ -0,0 +1,70 @@ +import { EntityManager } from "typeorm"; +import { EligibleECertDisbursement } from "../disbursement-schedule.models"; +import { ProcessSummary } from "@sims/utilities/logger"; + +/** + * Provides a basic structure for creating and + * sending notifications related to e-Cert disbursements. + */ +export abstract class ECertNotification { + /** + * Initializes a new instance of {@link ECertNotification}. + * @param notificationName friendly name of the notification for logging + */ + protected constructor(private readonly notificationName: string) {} + + /** + * Determines whether a notification should be created or not. + * This method must be implemented by derived classes. + * @param eCertDisbursement eligible disbursement to be potentially added to an e-Cert. + * @param entityManager entity manager to execute in transaction. + * @returns true if a notification should be created, false otherwise. + */ + protected abstract shouldCreateNotification( + eCertDisbursement: EligibleECertDisbursement, + entityManager: EntityManager, + ): Promise | boolean; + + /** + * Creates a notification for the given e-Cert disbursement. + * This method must be implemented by derived classes. + * @param eCertDisbursement eligible disbursement to be potentially added to an e-Cert. + * @param entityManager entity manager to execute in transaction. + */ + protected abstract createNotification( + eCertDisbursement: EligibleECertDisbursement, + entityManager: EntityManager, + ): Promise; + + /** + * Creates a notification defined by {@link createNotification} if the requirements + * defined by {@link shouldCreateNotification} are met. + * @param eCertDisbursement eligible disbursement to be potentially added to an e-Cert. + * @param entityManager entity manager to execute in transaction. + * @param log cumulative log summary. + * @returns true if the notification is created, false otherwise. + */ + async notify( + eCertDisbursement: EligibleECertDisbursement, + entityManager: EntityManager, + log: ProcessSummary, + ): Promise { + const notificationLog = new ProcessSummary(); + log.children(notificationLog); + const shouldCreateNotification = await this.shouldCreateNotification( + eCertDisbursement, + entityManager, + ); + if (!shouldCreateNotification) { + notificationLog.info( + `${this.notificationName} notification should not be created at this moment for disbursement ID ${eCertDisbursement.disbursement.id}.`, + ); + return false; + } + await this.createNotification(eCertDisbursement, entityManager); + notificationLog.info( + `${this.notificationName} notification created for disbursement ID ${eCertDisbursement.disbursement.id}.`, + ); + return true; + } +} diff --git a/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-notification/index.ts b/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-notification/index.ts new file mode 100644 index 0000000000..6bacef5ad6 --- /dev/null +++ b/sources/packages/backend/libs/integrations/src/services/disbursement-schedule/e-cert-notification/index.ts @@ -0,0 +1,4 @@ +export * from "./blocked-disbursement/ministry-blocked-disbursement-notification"; +export * from "./blocked-disbursement/student-blocked-disbursement-notification"; +export * from "./e-cert-notification"; +export * from "./e-cert-notification.service";