diff --git a/prime-angular-frontend/src/app/modules/adjudication/shared/components/authorized-user-review/authorized-user-review.component.html b/prime-angular-frontend/src/app/modules/adjudication/shared/components/authorized-user-review/authorized-user-review.component.html index 8eb999f816..4366da680f 100644 --- a/prime-angular-frontend/src/app/modules/adjudication/shared/components/authorized-user-review/authorized-user-review.component.html +++ b/prime-angular-frontend/src/app/modules/adjudication/shared/components/authorized-user-review/authorized-user-review.component.html @@ -21,6 +21,10 @@ {{ user?.preferredLastName | default }} + + + {{ user?.submittedDate | formatDate | default }} + Back - +
+ + +
diff --git a/prime-angular-frontend/src/app/modules/adjudication/shared/components/authorized-user-review/authorized-user-review.component.ts b/prime-angular-frontend/src/app/modules/adjudication/shared/components/authorized-user-review/authorized-user-review.component.ts index 845a615ea7..9b53f45166 100644 --- a/prime-angular-frontend/src/app/modules/adjudication/shared/components/authorized-user-review/authorized-user-review.component.ts +++ b/prime-angular-frontend/src/app/modules/adjudication/shared/components/authorized-user-review/authorized-user-review.component.ts @@ -1,10 +1,13 @@ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; +import { MatDialog } from '@angular/material/dialog'; import { Subscription } from 'rxjs'; import { RouteUtils } from '@lib/utils/route-utils.class'; +import { ConfirmDialogComponent } from '@shared/components/dialogs/confirm-dialog/confirm-dialog.component'; +import { DialogOptions } from '@shared/components/dialogs/dialog-options.model'; import { Config } from '@config/config.model'; import { ConfigService } from '@config/config.service'; import { AuthorizedUserResource } from '@core/resources/authorized-user-resource.service'; @@ -31,6 +34,7 @@ export class AuthorizedUserReviewComponent implements OnInit { private route: ActivatedRoute, private authorizedUserResource: AuthorizedUserResource, private configService: ConfigService, + private dialog: MatDialog, private router: Router ) { this.routeUtils = new RouteUtils(route, router, AdjudicationRoutes.HEALTH_AUTHORITIES); @@ -43,6 +47,25 @@ export class AuthorizedUserReviewComponent implements OnInit { .subscribe(() => this.routeUtils.routeRelativeTo(['../', AdjudicationRoutes.HEALTH_AUTH_AUTHORIZED_USERS])); } + public onDelete() { + + const data: DialogOptions = { + title: 'Delete Authorized User', + message: 'Are you sure you want to delete this authorized user request?', + actionText: "Yes" + }; + + this.dialog.open(ConfirmDialogComponent, { data }) + .afterClosed() + .subscribe((result: boolean) => { + if (result) { + this.authorizedUserResource + .deleteAuthorizedUser(this.route.snapshot.params.auid) + .subscribe(() => this.routeUtils.routeRelativeTo(['../', AdjudicationRoutes.HEALTH_AUTH_AUTHORIZED_USERS])); + } + }); + } + public onBack() { this.routeUtils.routeRelativeTo(['../', AdjudicationRoutes.HEALTH_AUTH_AUTHORIZED_USERS]); } diff --git a/prime-angular-frontend/src/app/modules/adjudication/shared/components/health-auth-authorized-users-view/health-auth-authorized-users-view.component.ts b/prime-angular-frontend/src/app/modules/adjudication/shared/components/health-auth-authorized-users-view/health-auth-authorized-users-view.component.ts index 521f7c2506..dd9737ee5f 100644 --- a/prime-angular-frontend/src/app/modules/adjudication/shared/components/health-auth-authorized-users-view/health-auth-authorized-users-view.component.ts +++ b/prime-angular-frontend/src/app/modules/adjudication/shared/components/health-auth-authorized-users-view/health-auth-authorized-users-view.component.ts @@ -5,6 +5,8 @@ import { Subscription } from 'rxjs'; import { RouteUtils } from '@lib/utils/route-utils.class'; +import { FormatDatePipe } from '@shared/pipes/format-date.pipe'; + import { HealthAuthorityResource } from '@core/resources/health-authority-resource.service'; import { AuthorizedUser } from '@shared/models/authorized-user.model'; @@ -14,7 +16,8 @@ import { AccessStatusEnum } from '@health-auth/shared/enums/access-status.enum'; @Component({ selector: 'app-health-auth-authorized-users-view', templateUrl: './health-auth-authorized-users-view.component.html', - styleUrls: ['./health-auth-authorized-users-view.component.scss'] + styleUrls: ['./health-auth-authorized-users-view.component.scss'], + providers: [FormatDatePipe] }) export class HealthAuthAuthorizedUsersViewComponent implements OnInit { public busy: Subscription; @@ -26,6 +29,7 @@ export class HealthAuthAuthorizedUsersViewComponent implements OnInit { private route: ActivatedRoute, private router: Router, private healthAuthorityResource: HealthAuthorityResource, + private formatDatePipe: FormatDatePipe, ) { this.routeUtils = new RouteUtils(route, router, AdjudicationRoutes.routePath(AdjudicationRoutes.SITE_REGISTRATIONS)); } @@ -47,7 +51,11 @@ export class HealthAuthAuthorizedUsersViewComponent implements OnInit { { key: 'Job Title', value: user.jobRoleTitle - } + }, + { + key: 'Submitted Date', + value: this.formatDatePipe.transform(user.submittedDate) + }, ]; } diff --git a/prime-angular-frontend/src/app/shared/components/auth/prime-enrolment-access/prime-enrolment-access.component.html b/prime-angular-frontend/src/app/shared/components/auth/prime-enrolment-access/prime-enrolment-access.component.html index 75dd29f1ee..350cb3a9ee 100644 --- a/prime-angular-frontend/src/app/shared/components/auth/prime-enrolment-access/prime-enrolment-access.component.html +++ b/prime-angular-frontend/src/app/shared/components/auth/prime-enrolment-access/prime-enrolment-access.component.html @@ -47,12 +47,12 @@
- Community sites + Community site registration
- Health authority sites + Health authority site registration
diff --git a/prime-angular-frontend/src/app/shared/models/authorized-user.model.ts b/prime-angular-frontend/src/app/shared/models/authorized-user.model.ts index ae83de548f..ae48ee04c1 100644 --- a/prime-angular-frontend/src/app/shared/models/authorized-user.model.ts +++ b/prime-angular-frontend/src/app/shared/models/authorized-user.model.ts @@ -5,4 +5,5 @@ import { AccessStatusEnum } from '@health-auth/shared/enums/access-status.enum'; export interface AuthorizedUser extends Party { healthAuthorityCode: HealthAuthorityEnum; status: AccessStatusEnum; + submittedDate: string; } diff --git a/prime-angular-frontend/src/test/mocks/mock-authorized-user.service.ts b/prime-angular-frontend/src/test/mocks/mock-authorized-user.service.ts index ee3370a524..fd9b2c22c6 100644 --- a/prime-angular-frontend/src/test/mocks/mock-authorized-user.service.ts +++ b/prime-angular-frontend/src/test/mocks/mock-authorized-user.service.ts @@ -28,6 +28,7 @@ export class MockAuthorizedUserService implements IAuthorizedUserService { healthAuthorityCode: HealthAuthorityEnum.FRASER_HEALTH, phone: faker.phone.phoneNumber(), status: AccessStatusEnum.UNDER_REVIEW, + submittedDate: faker.date.past().toISOString(), }); } diff --git a/prime-dotnet-webapi/ApiDbContext.cs b/prime-dotnet-webapi/ApiDbContext.cs index 41922bdd22..1fe55eae6c 100644 --- a/prime-dotnet-webapi/ApiDbContext.cs +++ b/prime-dotnet-webapi/ApiDbContext.cs @@ -120,6 +120,7 @@ IHttpContextAccessor context public DbSet Parties { get; set; } public DbSet PartySubmissions { get; set; } public DbSet PartyCertifications { get; set; } + public DbSet PartyEnrolments { get; set; } // PLR Integration public DbSet PlrProviders { get; set; } diff --git a/prime-dotnet-webapi/Controllers/AuthorizedUsersController.cs b/prime-dotnet-webapi/Controllers/AuthorizedUsersController.cs index b95abfc3ca..402052e0dd 100644 --- a/prime-dotnet-webapi/Controllers/AuthorizedUsersController.cs +++ b/prime-dotnet-webapi/Controllers/AuthorizedUsersController.cs @@ -240,5 +240,34 @@ public async Task ApproveAuthorizedUser(int authorizedUserId) return NoContent(); } + + + // DELETE: api/parties/authorized-user/5 + /// + /// Delete the authorized user. + /// + /// + [HttpDelete("{authorizedUserId}", Name = nameof(DeleteAuthorizedUser))] + [Authorize(Roles = Roles.PrimeSuperAdmin)] + [ProducesResponseType(StatusCodes.Status401Unauthorized)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ApiMessageResponse), StatusCodes.Status404NotFound)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public async Task DeleteAuthorizedUser(int authorizedUserId) + { + var authorizedUser = await _authorizedUserService.GetAuthorizedUserAsync(authorizedUserId); + if (authorizedUser == null) + { + return NotFound($"AuthorizedUser not found with id {authorizedUserId}"); + } + if (!authorizedUser.PermissionsRecord().AccessableBy(User)) + { + return Forbid(); + } + + await _authorizedUserService.DeleteAuthorizedUserAsync(authorizedUserId); + + return NoContent(); + } } } diff --git a/prime-dotnet-webapi/Models/Parties/PartyEnrolment.cs b/prime-dotnet-webapi/Models/Parties/PartyEnrolment.cs index 190a74d248..2ea8283b4b 100644 --- a/prime-dotnet-webapi/Models/Parties/PartyEnrolment.cs +++ b/prime-dotnet-webapi/Models/Parties/PartyEnrolment.cs @@ -1,8 +1,10 @@ using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; using Newtonsoft.Json; namespace Prime.Models { + [Table("PartyEnrolment")] public class PartyEnrolment : BaseAuditable { [Key] diff --git a/prime-dotnet-webapi/Services/AuthorizedUserService.cs b/prime-dotnet-webapi/Services/AuthorizedUserService.cs index ac6fbafa4d..63d8c6b942 100644 --- a/prime-dotnet-webapi/Services/AuthorizedUserService.cs +++ b/prime-dotnet-webapi/Services/AuthorizedUserService.cs @@ -132,7 +132,21 @@ public async Task DeleteAuthorizedUserAsync(int authorizedUserId) return; } - await _partyService.DeletePartyAsync(authorizedUser.Party.Id); + var auPartyEnrolment = await _context.PartyEnrolments.Where(p => p.PartyId == authorizedUser.PartyId && p.PartyType == PartyType.AuthorizedUser).FirstOrDefaultAsync(); + var nonAUPartyEnrolment = await _context.PartyEnrolments.Where(p => p.PartyId == authorizedUser.PartyId && p.PartyType != PartyType.AuthorizedUser).FirstOrDefaultAsync(); + + if (nonAUPartyEnrolment == null) + { + var party = await _context.Parties.Where(p => p.Id == authorizedUser.PartyId).FirstOrDefaultAsync(); + if (party != null) + { + _context.Parties.Remove(party); + } + } + _context.AuthorizedUsers.Remove(authorizedUser); + _context.PartyEnrolments.Remove(auPartyEnrolment); + + await _context.SaveChangesAsync(); } private IQueryable GetBaseAuthorizedUserQuery() diff --git a/prime-dotnet-webapi/ViewModels/Health Authorities/AuthorizedUserViewModel.cs b/prime-dotnet-webapi/ViewModels/Health Authorities/AuthorizedUserViewModel.cs index 9d85f39c66..a7689332e9 100644 --- a/prime-dotnet-webapi/ViewModels/Health Authorities/AuthorizedUserViewModel.cs +++ b/prime-dotnet-webapi/ViewModels/Health Authorities/AuthorizedUserViewModel.cs @@ -25,5 +25,6 @@ public class AuthorizedUserViewModel : IUserBoundModel public string JobRoleTitle { get; set; } public HealthAuthorityCode HealthAuthorityCode { get; set; } public AccessStatusType Status { get; set; } + public DateTimeOffset SubmittedDate { get; set; } } } diff --git a/prime-dotnet-webapi/ViewModels/Health Authorities/_HealthAuthorityMappingProfile.cs b/prime-dotnet-webapi/ViewModels/Health Authorities/_HealthAuthorityMappingProfile.cs index 6cd8de4910..e48f9cfbc7 100644 --- a/prime-dotnet-webapi/ViewModels/Health Authorities/_HealthAuthorityMappingProfile.cs +++ b/prime-dotnet-webapi/ViewModels/Health Authorities/_HealthAuthorityMappingProfile.cs @@ -38,7 +38,9 @@ public HealthAuthorityMappingProfile() CreateMap(); CreateMap() - .IncludeMembers(src => src.Party); + .IncludeMembers(src => src.Party) + .ForMember(dest => dest.SubmittedDate, opt => opt.MapFrom(src => src.CreatedTimeStamp)); + CreateMap(); } } diff --git a/prime-dotnet-webapi/prime-dotnet-webapi.sln b/prime-dotnet-webapi/prime-dotnet-webapi.sln new file mode 100644 index 0000000000..0212fae43e --- /dev/null +++ b/prime-dotnet-webapi/prime-dotnet-webapi.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.002.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "prime", "prime.csproj", "{3FC7F06B-7A36-4197-BB77-3095B85CDC1B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3FC7F06B-7A36-4197-BB77-3095B85CDC1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3FC7F06B-7A36-4197-BB77-3095B85CDC1B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3FC7F06B-7A36-4197-BB77-3095B85CDC1B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3FC7F06B-7A36-4197-BB77-3095B85CDC1B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {834C8FA2-C341-4A5E-A920-56EAA1A00294} + EndGlobalSection +EndGlobal