diff --git a/src/Api/Controllers/StaffsController.cs b/src/Api/Controllers/StaffsController.cs index 048f1b4c..7fdad81b 100644 --- a/src/Api/Controllers/StaffsController.cs +++ b/src/Api/Controllers/StaffsController.cs @@ -112,4 +112,25 @@ 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}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + 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..d550094b --- /dev/null +++ b/src/Application/Staffs/Commands/RemoveStaff.cs @@ -0,0 +1,45 @@ +using Application.Common.Interfaces; +using Application.Common.Models.Dtos.Physical; +using AutoMapper; +using FluentValidation; +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 + .Include(x => x.User) + .Include(x => x.Room) + .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/Staffs/Commands/RemoveStaffTests.cs b/tests/Application.Tests.Integration/Staffs/Commands/RemoveStaffTests.cs new file mode 100644 index 00000000..92df91b8 --- /dev/null +++ b/tests/Application.Tests.Integration/Staffs/Commands/RemoveStaffTests.cs @@ -0,0 +1,60 @@ +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() + { + // 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