diff --git a/alcs-frontend/src/app/features/notification/intake/intake.component.html b/alcs-frontend/src/app/features/notification/intake/intake.component.html index 5e525ced6f..95f810c5e9 100644 --- a/alcs-frontend/src/app/features/notification/intake/intake.component.html +++ b/alcs-frontend/src/app/features/notification/intake/intake.component.html @@ -23,7 +23,7 @@

ALC Intake

Sent - {{ responseDate | momentFormat }} + {{ responseDate | momentFormat }} @@ -44,6 +44,6 @@

ALC Intake

Primary Contact Email
- +
diff --git a/alcs-frontend/src/app/features/notification/intake/intake.component.ts b/alcs-frontend/src/app/features/notification/intake/intake.component.ts index cb29df65db..19f5046699 100644 --- a/alcs-frontend/src/app/features/notification/intake/intake.component.ts +++ b/alcs-frontend/src/app/features/notification/intake/intake.component.ts @@ -59,7 +59,26 @@ export class IntakeComponent implements OnInit { } async updateSubmissionEmail(email: string | null) { - //TODO: Implemented in ALCS-1074 + if (!email) { + return; + } + + this.confirmationDialogService + .openDialog({ + title: 'Change Primary Contact Email', + body: 'Any changes made here will also be reflected in the portal. Do you want to continue?', + }) + .subscribe(async (didConfirm) => { + if (didConfirm) { + const notification = this.notification; + if (notification) { + const update = await this.notificationSubmissionService.setContactEmail(email, notification.fileNumber); + if (update) { + this.toastService.showSuccessToast('Notification updated'); + } + } + } + }); } private async loadGovernments() { diff --git a/alcs-frontend/src/app/services/notification/notification-submission/notification-submission.service.spec.ts b/alcs-frontend/src/app/services/notification/notification-submission/notification-submission.service.spec.ts index 3f11c21bff..a04f2c9c6f 100644 --- a/alcs-frontend/src/app/services/notification/notification-submission/notification-submission.service.spec.ts +++ b/alcs-frontend/src/app/services/notification/notification-submission/notification-submission.service.spec.ts @@ -70,4 +70,13 @@ describe('NotificationSubmissionService', () => { expect(result).toEqual(mockSubmittedNOI); expect(mockHttpClient.get).toBeCalledTimes(1); }); + + it('should make a patch request for email', async () => { + mockHttpClient.patch.mockReturnValue(of(mockSubmittedNOI)); + + const result = await service.setContactEmail('1', '1'); + + expect(result).toEqual(mockSubmittedNOI); + expect(mockHttpClient.patch).toBeCalledTimes(1); + }); }); diff --git a/alcs-frontend/src/app/services/notification/notification-submission/notification-submission.service.ts b/alcs-frontend/src/app/services/notification/notification-submission/notification-submission.service.ts index fade1b19e7..e41fb04a10 100644 --- a/alcs-frontend/src/app/services/notification/notification-submission/notification-submission.service.ts +++ b/alcs-frontend/src/app/services/notification/notification-submission/notification-submission.service.ts @@ -22,6 +22,19 @@ export class NotificationSubmissionService { } } + async setContactEmail(email: string, fileNumber: string): Promise { + try { + return firstValueFrom( + this.http.patch(`${this.baseUrl}/${fileNumber}`, { + contactEmail: email, + }) + ); + } catch (e) { + this.toastService.showErrorToast('Failed to fetch Notification Submission'); + throw e; + } + } + async setSubmissionStatus(fileNumber: string, statusCode: string): Promise { try { return firstValueFrom( diff --git a/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.html b/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.html index 459ba27e1e..142c0b9f0c 100644 --- a/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.html +++ b/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.html @@ -30,7 +30,7 @@
- +
diff --git a/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.ts b/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.ts index 09aefe8b93..cf659714ba 100644 --- a/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.ts +++ b/alcs-frontend/src/app/shared/inline-editors/inline-text/inline-text.component.ts @@ -8,6 +8,7 @@ import { AfterContentChecked, Component, ElementRef, EventEmitter, Input, Output export class InlineTextComponent implements AfterContentChecked { @Input() value?: string | undefined; @Input() placeholder: string = 'Enter a value'; + @Input() required = false; @Output() save = new EventEmitter(); @ViewChild('editInput') textInput!: ElementRef; diff --git a/services/apps/alcs/src/alcs/notification/notification-submission/notification-submission.controller.spec.ts b/services/apps/alcs/src/alcs/notification/notification-submission/notification-submission.controller.spec.ts index 60fe5763c2..52745f1826 100644 --- a/services/apps/alcs/src/alcs/notification/notification-submission/notification-submission.controller.spec.ts +++ b/services/apps/alcs/src/alcs/notification/notification-submission/notification-submission.controller.spec.ts @@ -93,4 +93,28 @@ describe('NotificationSubmissionController', () => { ); expect(result).toEqual({ url: fakeDownloadUrl }); }); + + it('should call through to service for updating email', async () => { + mockNotificationSubmissionService.getUuid.mockResolvedValue('uuid'); + mockNotificationSubmissionService.update.mockResolvedValue( + new NotificationSubmission(), + ); + mockNotificationSubmissionService.getByFileNumber.mockResolvedValue( + new NotificationSubmission({ + fileNumber: 'fileNumber', + }), + ); + mockNotificationSubmissionService.mapToDetailedDTO.mockResolvedValue( + createMock(), + ); + + await controller.update('fileNumber', 'email', { + user: { + entity: new User(), + }, + }); + + expect(mockNotificationSubmissionService.getUuid).toBeCalledTimes(1); + expect(mockNotificationSubmissionService.update).toBeCalledTimes(1); + }); }); diff --git a/services/apps/alcs/src/alcs/notification/notification-submission/notification-submission.controller.ts b/services/apps/alcs/src/alcs/notification/notification-submission/notification-submission.controller.ts index 668aa43308..95fa7a7e96 100644 --- a/services/apps/alcs/src/alcs/notification/notification-submission/notification-submission.controller.ts +++ b/services/apps/alcs/src/alcs/notification/notification-submission/notification-submission.controller.ts @@ -64,4 +64,29 @@ export class NotificationSubmissionController { ); return this.get(fileNumber, req); } + + @UserRoles(...ANY_AUTH_ROLE) + @Patch('/:fileNumber') + async update( + @Param('fileNumber') fileNumber: string, + @Body('contactEmail') contactEmail: string, + @Req() req, + ) { + if (!contactEmail.trim()) { + throw new ServiceValidationException('Email is required'); + } + + const uuid = await this.notificationSubmissionService.getUuid(fileNumber); + if (uuid) { + await this.notificationSubmissionService.update( + uuid, + { + contactEmail, + }, + req.user.entity, + ); + } + + return this.get(fileNumber, req); + } } 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 affe4397ea..3f103961ea 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 @@ -278,4 +278,30 @@ describe('NotificationSubmissionService', () => { expect(app).toBe(noiSubmission); }); + + it('should call through to the repo for getFileNumber', async () => { + const fileNumber = 'file-number'; + const noiSubmission = new NotificationSubmission({ + fileNumber, + }); + mockRepository.findOne.mockResolvedValue(noiSubmission); + + const res = await service.getFileNumber('uuid'); + + expect(res).toBe(fileNumber); + expect(mockRepository.findOne).toHaveBeenCalledTimes(1); + }); + + it('should call through to the repo for getUuid', async () => { + const uuid = 'uuid'; + const noiSubmission = new NotificationSubmission({ + uuid, + }); + mockRepository.findOne.mockResolvedValue(noiSubmission); + + const res = await service.getUuid('file-number'); + + expect(res).toBe(uuid); + expect(mockRepository.findOne).toHaveBeenCalledTimes(1); + }); }); 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 dfc304e878..ff550de8ab 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 @@ -169,6 +169,19 @@ export class NotificationSubmissionService { return submission?.fileNumber; } + async getUuid(fileNumber: string) { + const submission = await this.notificationSubmissionRepository.findOne({ + where: { + fileNumber, + }, + select: { + uuid: true, + fileNumber: true, + }, + }); + return submission?.uuid; + } + async getAllByUser(user: User) { const whereClauses = await this.generateWhereClauses({}, user);