From a43bb62f3adf88c747373482ffdd50bba596b97c Mon Sep 17 00:00:00 2001 From: Daniel Haselhan Date: Fri, 22 Sep 2023 14:38:57 -0700 Subject: [PATCH] Only set ALC Response Sent status if Noti Email Sends * Add tests for it * Update email service to return true/false * Minor UI fix to Inbox --- .../application-list.component.html | 2 +- .../src/app/features/home/home.component.scss | 8 ++ .../home/noi-list/noi-list.component.html | 2 +- .../notification-list.component.html | 2 +- .../notification-submission.service.spec.ts | 89 +++++++++++++++++++ .../notification-submission.service.ts | 50 +++++------ .../alcs/src/providers/email/email.service.ts | 5 +- .../email/status-email.service.spec.ts | 2 +- .../application-expiry.consumer.spec.ts | 2 +- .../apps/alcs/src/user/user.service.spec.ts | 2 +- 10 files changed, 132 insertions(+), 32 deletions(-) diff --git a/portal-frontend/src/app/features/home/application-list/application-list.component.html b/portal-frontend/src/app/features/home/application-list/application-list.component.html index 719877d75c..d169340042 100644 --- a/portal-frontend/src/app/features/home/application-list/application-list.component.html +++ b/portal-frontend/src/app/features/home/application-list/application-list.component.html @@ -6,7 +6,7 @@ - No Applications Created + No Applications Created diff --git a/portal-frontend/src/app/features/home/home.component.scss b/portal-frontend/src/app/features/home/home.component.scss index 6e3266e0d0..e7b75a145d 100644 --- a/portal-frontend/src/app/features/home/home.component.scss +++ b/portal-frontend/src/app/features/home/home.component.scss @@ -7,6 +7,14 @@ } } +:host::ng-deep { + .no-data { + color: colors.$grey; + text-align: center; + padding: rem(8); + } +} + .header-row { .learn-more-wrapper { margin-top: rem(24); diff --git a/portal-frontend/src/app/features/home/noi-list/noi-list.component.html b/portal-frontend/src/app/features/home/noi-list/noi-list.component.html index e9e9d22972..52b16f25e4 100644 --- a/portal-frontend/src/app/features/home/noi-list/noi-list.component.html +++ b/portal-frontend/src/app/features/home/noi-list/noi-list.component.html @@ -6,7 +6,7 @@ - No NOIs Created + No NOIs Created diff --git a/portal-frontend/src/app/features/home/notification-list/notification-list.component.html b/portal-frontend/src/app/features/home/notification-list/notification-list.component.html index a0f3cf3e36..0322d6b0ab 100644 --- a/portal-frontend/src/app/features/home/notification-list/notification-list.component.html +++ b/portal-frontend/src/app/features/home/notification-list/notification-list.component.html @@ -6,7 +6,7 @@ - No Notifications Created + No Notifications Created diff --git a/services/apps/alcs/src/portal/notification-submission/notification-submission.service.spec.ts b/services/apps/alcs/src/portal/notification-submission/notification-submission.service.spec.ts index 3f103961ea..cbb18ca66b 100644 --- a/services/apps/alcs/src/portal/notification-submission/notification-submission.service.spec.ts +++ b/services/apps/alcs/src/portal/notification-submission/notification-submission.service.spec.ts @@ -5,9 +5,12 @@ import { createMock, DeepMocked } from '@golevelup/nestjs-testing'; import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; +import { LocalGovernment } from '../../alcs/local-government/local-government.entity'; import { LocalGovernmentService } from '../../alcs/local-government/local-government.service'; import { NoticeOfIntentType } from '../../alcs/notice-of-intent/notice-of-intent-type/notice-of-intent-type.entity'; +import { NotificationDocument } from '../../alcs/notification/notification-document/notification-document.entity'; import { NotificationDocumentService } from '../../alcs/notification/notification-document/notification-document.service'; +import { NOTIFICATION_STATUS } from '../../alcs/notification/notification-submission-status/notification-status.dto'; import { NotificationSubmissionToSubmissionStatus } from '../../alcs/notification/notification-submission-status/notification-status.entity'; import { NotificationSubmissionStatusService } from '../../alcs/notification/notification-submission-status/notification-submission-status.service'; import { Notification } from '../../alcs/notification/notification.entity'; @@ -19,6 +22,7 @@ import { User } from '../../user/user.entity'; import { ValidatedNotificationSubmission } from './notification-submission-validator.service'; import { NotificationSubmission } from './notification-submission.entity'; import { NotificationSubmissionService } from './notification-submission.service'; +import { Document } from '../../document/document.entity'; describe('NotificationSubmissionService', () => { let service: NotificationSubmissionService; @@ -304,4 +308,89 @@ describe('NotificationSubmissionService', () => { expect(res).toBe(uuid); expect(mockRepository.findOne).toHaveBeenCalledTimes(1); }); + + it('should change the status when sending the email was successfull', async () => { + const uuid = 'uuid'; + const noiSubmission = new NotificationSubmission({ + uuid, + localGovernmentUuid: 'uuid', + contactEmail: 'contact@contact', + }); + const document = new NotificationDocument({ + document: new Document(), + }); + + mockLGService.getByUuid.mockResolvedValue( + new LocalGovernment({ + emails: ['gov@gov'], + }), + ); + mockNotificationService.getByFileNumber.mockResolvedValue( + new Notification(), + ); + mockEmailService.sendEmail.mockResolvedValue(true); + mockDocumentService.attachDocumentAsBuffer.mockResolvedValue( + new NotificationDocument(), + ); + mockStatusService.setStatusDate.mockResolvedValue( + new NotificationSubmissionToSubmissionStatus(), + ); + + await service.sendAndRecordLTSAPackage(noiSubmission, document, new User()); + + expect(mockLGService.getByUuid).toHaveBeenCalledTimes(1); + expect(mockNotificationService.getByFileNumber).toHaveBeenCalledTimes(1); + expect(mockEmailService.sendEmail).toHaveBeenCalledTimes(1); + expect(mockEmailService.sendEmail).toHaveBeenCalledWith( + expect.objectContaining({ + to: ['contact@contact'], + cc: ['gov@gov'], + }), + ); + + expect(mockDocumentService.attachDocumentAsBuffer).toHaveBeenCalledTimes(1); + expect(mockStatusService.setStatusDate).toHaveBeenCalledTimes(1); + expect(mockStatusService.setStatusDate).toHaveBeenCalledWith( + uuid, + NOTIFICATION_STATUS.ALC_RESPONSE_SENT, + undefined, + ); + }); + + it('should not change the status if the email fails', async () => { + const uuid = 'uuid'; + const noiSubmission = new NotificationSubmission({ + uuid, + localGovernmentUuid: 'uuid', + contactEmail: 'contact@contact', + }); + const document = new NotificationDocument({ + document: new Document(), + }); + + mockLGService.getByUuid.mockResolvedValue( + new LocalGovernment({ + emails: ['gov@gov'], + }), + ); + mockNotificationService.getByFileNumber.mockResolvedValue( + new Notification(), + ); + mockEmailService.sendEmail.mockResolvedValue(false); + + await service.sendAndRecordLTSAPackage(noiSubmission, document, new User()); + + expect(mockLGService.getByUuid).toHaveBeenCalledTimes(1); + expect(mockNotificationService.getByFileNumber).toHaveBeenCalledTimes(1); + expect(mockEmailService.sendEmail).toHaveBeenCalledTimes(1); + expect(mockEmailService.sendEmail).toHaveBeenCalledWith( + expect.objectContaining({ + to: ['contact@contact'], + cc: ['gov@gov'], + }), + ); + + expect(mockDocumentService.attachDocumentAsBuffer).toHaveBeenCalledTimes(0); + expect(mockStatusService.setStatusDate).toHaveBeenCalledTimes(0); + }); }); diff --git a/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts b/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts index ff550de8ab..68e9dd8571 100644 --- a/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts +++ b/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts @@ -380,9 +380,8 @@ export class NotificationSubmissionService { statusCode: NOTIFICATION_STATUS, effectiveDate?: Date | null, ) { - const submission = await this.loadBarebonesSubmission(uuid); await this.notificationSubmissionStatusService.setStatusDate( - submission.uuid, + uuid, statusCode, effectiveDate, ); @@ -411,7 +410,7 @@ export class NotificationSubmissionService { ) { const templateData = await this.generateSrwEmailData(submission, document); - await this.emailService.sendEmail({ + const didSend = await this.emailService.sendEmail({ to: [templateData.to], body: templateData.html, subject: `Agricultural Land Commission SRW${submission.fileNumber} (${submission.applicant})`, @@ -421,24 +420,29 @@ export class NotificationSubmissionService { attachments: [document.document], }); - const fileBuffer = Buffer.from(templateData.html); - await this.notificationDocumentService.attachDocumentAsBuffer({ - file: Buffer.from(templateData.html), - fileName: `SRW${submission.fileNumber}_ALC_Email_Response.html`, - source: DOCUMENT_SOURCE.ALC, - user, - system: DOCUMENT_SYSTEM.ALCS, - documentType: DOCUMENT_TYPE.ACKNOWLEDGEMENT_LETTER, - fileNumber: submission.fileNumber, - fileSize: fileBuffer.length, - mimeType: 'text/html', - visibilityFlags: [VISIBILITY_FLAG.APPLICANT, VISIBILITY_FLAG.GOVERNMENT], - }); + if (didSend) { + const fileBuffer = Buffer.from(templateData.html); + await this.notificationDocumentService.attachDocumentAsBuffer({ + file: Buffer.from(templateData.html), + fileName: `SRW${submission.fileNumber}_ALC_Email_Response.html`, + source: DOCUMENT_SOURCE.ALC, + user, + system: DOCUMENT_SYSTEM.ALCS, + documentType: DOCUMENT_TYPE.ACKNOWLEDGEMENT_LETTER, + fileNumber: submission.fileNumber, + fileSize: fileBuffer.length, + mimeType: 'text/html', + visibilityFlags: [ + VISIBILITY_FLAG.APPLICANT, + VISIBILITY_FLAG.GOVERNMENT, + ], + }); - await this.updateStatus( - submission.uuid, - NOTIFICATION_STATUS.ALC_RESPONSE_SENT, - ); + await this.updateStatus( + submission.uuid, + NOTIFICATION_STATUS.ALC_RESPONSE_SENT, + ); + } } private async generateSrwEmailData( @@ -471,15 +475,11 @@ export class NotificationSubmissionService { } } - const parentId = await this.notificationService.getUuid( - submission.fileNumber, - ); - return { html: emailTemplate.html, cc: ccEmails, to: submission.contactEmail!, - parentId, + parentId: notification.uuid, }; } } diff --git a/services/apps/alcs/src/providers/email/email.service.ts b/services/apps/alcs/src/providers/email/email.service.ts index 0b9af52c56..eccac508bd 100644 --- a/services/apps/alcs/src/providers/email/email.service.ts +++ b/services/apps/alcs/src/providers/email/email.service.ts @@ -164,7 +164,7 @@ export class EmailService { ), ); this.logger.debug({ to, from, subject }, `Email sent`); - this.repository.save( + await this.repository.save( new EmailStatus({ recipients: [...to, ...cc, ...bcc].join(', '), status: 'success', @@ -174,6 +174,7 @@ export class EmailService { triggerStatus, }), ); + return true; } catch (e) { this.logger.error(e, 'Failed to Send Email'); @@ -192,6 +193,8 @@ export class EmailService { triggerStatus, }), ); + + return false; } } } diff --git a/services/apps/alcs/src/providers/email/status-email.service.spec.ts b/services/apps/alcs/src/providers/email/status-email.service.spec.ts index 3755095d46..1e86e41e6e 100644 --- a/services/apps/alcs/src/providers/email/status-email.service.spec.ts +++ b/services/apps/alcs/src/providers/email/status-email.service.spec.ts @@ -70,7 +70,7 @@ describe('StatusEmailService', () => { service = module.get(StatusEmailService); - mockEmailService.sendEmail.mockResolvedValue(); + mockEmailService.sendEmail.mockResolvedValue(true); }); it('should be defined', () => { diff --git a/services/apps/alcs/src/queues/scheduler/application/application-expiry/application-expiry.consumer.spec.ts b/services/apps/alcs/src/queues/scheduler/application/application-expiry/application-expiry.consumer.spec.ts index 2561f4bdaf..998d1e3a9a 100644 --- a/services/apps/alcs/src/queues/scheduler/application/application-expiry/application-expiry.consumer.spec.ts +++ b/services/apps/alcs/src/queues/scheduler/application/application-expiry/application-expiry.consumer.spec.ts @@ -37,7 +37,7 @@ describe('SchedulerConsumerService', () => { ApplicationExpiryConsumer, ); - mockEmailService.sendEmail.mockResolvedValue(); + mockEmailService.sendEmail.mockResolvedValue(true); }); it('should be defined', () => { diff --git a/services/apps/alcs/src/user/user.service.spec.ts b/services/apps/alcs/src/user/user.service.spec.ts index 7503389e71..f670312fc0 100644 --- a/services/apps/alcs/src/user/user.service.spec.ts +++ b/services/apps/alcs/src/user/user.service.spec.ts @@ -62,7 +62,7 @@ describe('UserService', () => { mockUserRepository.find.mockResolvedValue([mockUser]); mockUserRepository.softRemove.mockResolvedValue(mockUser); - emailServiceMock.sendEmail.mockResolvedValue(); + emailServiceMock.sendEmail.mockResolvedValue(true); }); it('should return the users from the repository', async () => {