From 4b6974bb2103836324fedcf4835cfc54b1124779 Mon Sep 17 00:00:00 2001 From: Vzart Date: Thu, 1 Jun 2023 18:05:17 +0700 Subject: [PATCH 1/4] add: Remove staff --- src/Api/Controllers/StaffsController.cs | 18 ++++++++ .../Staffs/Commands/RemoveStaff.cs | 42 +++++++++++++++++++ .../CustomApiFactory.cs | 2 +- 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/Application/Staffs/Commands/RemoveStaff.cs diff --git a/src/Api/Controllers/StaffsController.cs b/src/Api/Controllers/StaffsController.cs index 048f1b4c..40573ce7 100644 --- a/src/Api/Controllers/StaffsController.cs +++ b/src/Api/Controllers/StaffsController.cs @@ -112,4 +112,22 @@ public async Task>> RemoveFromRoom( var result = await Mediator.Send(command); return Ok(Result.Succeed(result)); } + + /// + /// Remove a staff + /// + /// Id of the staff to be removed + /// A StaffDto of the removed staff + [HttpDelete("{staffId:guid}")] + public async Task>> Remove( + [FromRoute] Guid staffId) + { + var command = new RemoveStaff.Command() + { + StaffId = staffId + }; + + var result = await Mediator.Send(command); + return Ok(Result.Succeed(result)); + } } \ No newline at end of file diff --git a/src/Application/Staffs/Commands/RemoveStaff.cs b/src/Application/Staffs/Commands/RemoveStaff.cs new file mode 100644 index 00000000..d356c950 --- /dev/null +++ b/src/Application/Staffs/Commands/RemoveStaff.cs @@ -0,0 +1,42 @@ +using Application.Common.Interfaces; +using Application.Common.Models.Dtos.Physical; +using AutoMapper; +using MediatR; +using Microsoft.EntityFrameworkCore; + +namespace Application.Staffs.Commands; + +public class RemoveStaff +{ + public record Command : IRequest + { + public Guid StaffId { get; init; } + } + + public class CommandHandler : IRequestHandler + { + private readonly IApplicationDbContext _context; + private readonly IMapper _mapper; + + public CommandHandler(IApplicationDbContext context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task Handle(Command request, CancellationToken cancellationToken) + { + var staff = await _context.Staffs + .FirstOrDefaultAsync(x => x.User.Id.Equals(request.StaffId), cancellationToken: cancellationToken); + + if (staff is null) + { + throw new KeyNotFoundException("Staff does not exist."); + } + + var result = _context.Staffs.Remove(staff); + await _context.SaveChangesAsync(cancellationToken); + return _mapper.Map(result.Entity); + } + } +} \ No newline at end of file diff --git a/tests/Application.Tests.Integration/CustomApiFactory.cs b/tests/Application.Tests.Integration/CustomApiFactory.cs index f76d4ac3..a4b2c7f1 100644 --- a/tests/Application.Tests.Integration/CustomApiFactory.cs +++ b/tests/Application.Tests.Integration/CustomApiFactory.cs @@ -28,7 +28,7 @@ protected override void ConfigureWebHost(IWebHostBuilder builder) var databaseSettings = GetConfiguration().GetSection(nameof(DatabaseSettings)).Get(); services.AddDbContext(options => { - options.UseNpgsql(databaseSettings!.ConnectionString, optionsBuilder => optionsBuilder.UseNodaTime()); + options.UseNpgsql("Server=localhost;Port=5432;Database=mytestdb;User ID=profiletester;Password=supasupasecured", optionsBuilder => optionsBuilder.UseNodaTime()); }); }); } From a4cb1c67671045c720a3ab17751d9c479daaaaa0 Mon Sep 17 00:00:00 2001 From: Vzart Date: Thu, 1 Jun 2023 19:00:42 +0700 Subject: [PATCH 2/4] test: add test for remove staff --- .../Staffs/Commands/RemoveStaff.cs | 13 +++++ .../Staffs/Commands/RemoveStaffTests.cs | 49 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 tests/Application.Tests.Integration/Staffs/Commands/RemoveStaffTests.cs diff --git a/src/Application/Staffs/Commands/RemoveStaff.cs b/src/Application/Staffs/Commands/RemoveStaff.cs index d356c950..ab3a0c73 100644 --- a/src/Application/Staffs/Commands/RemoveStaff.cs +++ b/src/Application/Staffs/Commands/RemoveStaff.cs @@ -1,6 +1,7 @@ using Application.Common.Interfaces; using Application.Common.Models.Dtos.Physical; using AutoMapper; +using FluentValidation; using MediatR; using Microsoft.EntityFrameworkCore; @@ -8,6 +9,16 @@ namespace Application.Staffs.Commands; public class RemoveStaff { + public class Validator : AbstractValidator + { + public Validator() + { + RuleLevelCascadeMode = CascadeMode.Stop; + + RuleFor(x => x.StaffId) + .NotEmpty().WithMessage("StaffId is required."); + } + } public record Command : IRequest { public Guid StaffId { get; init; } @@ -27,6 +38,8 @@ public CommandHandler(IApplicationDbContext context, IMapper mapper) public async Task Handle(Command request, CancellationToken cancellationToken) { var staff = await _context.Staffs + .Include(x => x.User) + .Include(x => x.Room) .FirstOrDefaultAsync(x => x.User.Id.Equals(request.StaffId), cancellationToken: cancellationToken); if (staff is null) diff --git a/tests/Application.Tests.Integration/Staffs/Commands/RemoveStaffTests.cs b/tests/Application.Tests.Integration/Staffs/Commands/RemoveStaffTests.cs new file mode 100644 index 00000000..80103078 --- /dev/null +++ b/tests/Application.Tests.Integration/Staffs/Commands/RemoveStaffTests.cs @@ -0,0 +1,49 @@ +using Application.Identity; +using Application.Staffs.Commands; +using Domain.Entities; +using Domain.Entities.Physical; +using FluentAssertions; +using Xunit; + +namespace Application.Tests.Integration.Staffs.Commands; + +public class RemoveStaffTests : BaseClassFixture +{ + public RemoveStaffTests(CustomApiFactory apiFactory) : base(apiFactory) + { + } + + [Fact] + public async Task ShouldRemoveStaff_WhenStaffIdIsValid() + { + // Arrange + var department = CreateDepartment(); + var user = CreateUser(IdentityData.Roles.Admin, "123456"); + var room = CreateRoom(department); + var staff = CreateStaff(user, room); + await AddAsync(staff); + + var command = new RemoveStaff.Command() + { + StaffId = staff.Id + }; + + // Act + await SendAsync(command); + + // Assert + var result = await FindAsync(staff.Id); + result.Should().BeNull(); + + // Cleanup + Remove(await FindAsync(room.Id)); + Remove(user); + Remove(await FindAsync(department.Id)); + } + + [Fact] + public async Task ShouldThrowKeyNotFoundException_WhenStaffDoesNotExist() + { + + } +} \ No newline at end of file From 28ed0f90a9fce8ad14f2458c1f59dad1dc756811 Mon Sep 17 00:00:00 2001 From: Vzart Date: Thu, 1 Jun 2023 19:27:38 +0700 Subject: [PATCH 3/4] test: add test --- src/Application/Staffs/Commands/RemoveStaff.cs | 10 ---------- .../CustomApiFactory.cs | 2 +- .../Staffs/Commands/RemoveStaffTests.cs | 13 ++++++++++++- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/Application/Staffs/Commands/RemoveStaff.cs b/src/Application/Staffs/Commands/RemoveStaff.cs index ab3a0c73..d550094b 100644 --- a/src/Application/Staffs/Commands/RemoveStaff.cs +++ b/src/Application/Staffs/Commands/RemoveStaff.cs @@ -9,16 +9,6 @@ namespace Application.Staffs.Commands; public class RemoveStaff { - public class Validator : AbstractValidator - { - public Validator() - { - RuleLevelCascadeMode = CascadeMode.Stop; - - RuleFor(x => x.StaffId) - .NotEmpty().WithMessage("StaffId is required."); - } - } public record Command : IRequest { public Guid StaffId { get; init; } diff --git a/tests/Application.Tests.Integration/CustomApiFactory.cs b/tests/Application.Tests.Integration/CustomApiFactory.cs index a4b2c7f1..f76d4ac3 100644 --- a/tests/Application.Tests.Integration/CustomApiFactory.cs +++ b/tests/Application.Tests.Integration/CustomApiFactory.cs @@ -28,7 +28,7 @@ protected override void ConfigureWebHost(IWebHostBuilder builder) var databaseSettings = GetConfiguration().GetSection(nameof(DatabaseSettings)).Get(); services.AddDbContext(options => { - options.UseNpgsql("Server=localhost;Port=5432;Database=mytestdb;User ID=profiletester;Password=supasupasecured", optionsBuilder => optionsBuilder.UseNodaTime()); + options.UseNpgsql(databaseSettings!.ConnectionString, optionsBuilder => optionsBuilder.UseNodaTime()); }); }); } diff --git a/tests/Application.Tests.Integration/Staffs/Commands/RemoveStaffTests.cs b/tests/Application.Tests.Integration/Staffs/Commands/RemoveStaffTests.cs index 80103078..92df91b8 100644 --- a/tests/Application.Tests.Integration/Staffs/Commands/RemoveStaffTests.cs +++ b/tests/Application.Tests.Integration/Staffs/Commands/RemoveStaffTests.cs @@ -44,6 +44,17 @@ public async Task ShouldRemoveStaff_WhenStaffIdIsValid() [Fact] public async Task ShouldThrowKeyNotFoundException_WhenStaffDoesNotExist() { - + // Arrange + var command = new RemoveStaff.Command() + { + StaffId = Guid.NewGuid() + }; + + // Act + var action = async () => await SendAsync(command); + + // Assert + await action.Should().ThrowAsync() + .WithMessage("Staff does not exist."); } } \ No newline at end of file From 98ba4bbea0eb0f5b42cc4b104780575cffa7b81a Mon Sep 17 00:00:00 2001 From: Vzart Date: Thu, 1 Jun 2023 19:57:29 +0700 Subject: [PATCH 4/4] add: documentation for endpoint --- src/Api/Controllers/StaffsController.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Api/Controllers/StaffsController.cs b/src/Api/Controllers/StaffsController.cs index 40573ce7..7fdad81b 100644 --- a/src/Api/Controllers/StaffsController.cs +++ b/src/Api/Controllers/StaffsController.cs @@ -119,6 +119,9 @@ public async Task>> RemoveFromRoom( /// Id of the staff to be removed /// A StaffDto of the removed staff [HttpDelete("{staffId:guid}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task>> Remove( [FromRoute] Guid staffId) {