From 4917b512068d93f568e492ab2f4189d0b9aceaa3 Mon Sep 17 00:00:00 2001 From: StarryFolf Date: Wed, 14 Jun 2023 09:35:40 +0700 Subject: [PATCH 1/4] feat: implement getting all logs and by Id for lockers --- src/Api/Controllers/LockersController.cs | 49 ++++++++++++- .../GetAllLogsPaginatedQueryParameters.cs | 6 ++ .../Models/Dtos/Logging/LockerLogDto.cs | 25 +++++++ .../Queries/GetAllLockerLogsPaginated.cs | 68 +++++++++++++++++++ .../Lockers/Queries/GetLockerLogById.cs | 43 ++++++++++++ 5 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 src/Api/Controllers/Payload/Requests/GetAllLogsPaginatedQueryParameters.cs create mode 100644 src/Application/Common/Models/Dtos/Logging/LockerLogDto.cs create mode 100644 src/Application/Lockers/Queries/GetAllLockerLogsPaginated.cs create mode 100644 src/Application/Lockers/Queries/GetLockerLogById.cs diff --git a/src/Api/Controllers/LockersController.cs b/src/Api/Controllers/LockersController.cs index 2799e670..b1543c4c 100644 --- a/src/Api/Controllers/LockersController.cs +++ b/src/Api/Controllers/LockersController.cs @@ -1,6 +1,8 @@ -using Api.Controllers.Payload.Requests.Lockers; +using Api.Controllers.Payload.Requests; +using Api.Controllers.Payload.Requests.Lockers; using Application.Common.Interfaces; using Application.Common.Models; +using Application.Common.Models.Dtos.Logging; using Application.Common.Models.Dtos.Physical; using Application.Identity; using Application.Lockers.Commands; @@ -178,4 +180,49 @@ public async Task>> Update([FromRoute] Guid locke var result = await Mediator.Send(command); return Ok(Result.Succeed(result)); } + + /// + /// Get all logs related to locker. + /// + /// Query parameters + /// A list of LockerLogsDtos. + [RequiresRole(IdentityData.Roles.Admin)] + [HttpGet("logs")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + public async Task>>> GetAllFolderLogs( + [FromQuery] GetAllLogsPaginatedQueryParameters queryParameters) + { + var query = new GetAllLockerLogsPaginated.Query() + { + SearchTerm = queryParameters.SearchTerm, + Page = queryParameters.Page, + Size = queryParameters.Size, + SortBy = queryParameters.SortBy, + SortOrder = queryParameters.SortOrder, + }; + var result = await Mediator.Send(query); + return Ok(Result>.Succeed(result)); + } + + /// + /// Get a log related to locker by Id. + /// + /// Id of the requested log + /// A LockerLogDto of the requested log. + [RequiresRole(IdentityData.Roles.Admin)] + [HttpGet("log/{logId:guid}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status403Forbidden)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public async Task>> GetUserLogById([FromRoute] Guid logId) + { + var query = new GetLockerLogById.Query() + { + LogId = logId + }; + + var result = await Mediator.Send(query); + return Ok(Result.Succeed(result)); + } } diff --git a/src/Api/Controllers/Payload/Requests/GetAllLogsPaginatedQueryParameters.cs b/src/Api/Controllers/Payload/Requests/GetAllLogsPaginatedQueryParameters.cs new file mode 100644 index 00000000..0a6a2903 --- /dev/null +++ b/src/Api/Controllers/Payload/Requests/GetAllLogsPaginatedQueryParameters.cs @@ -0,0 +1,6 @@ +namespace Api.Controllers.Payload.Requests; + +public class GetAllLogsPaginatedQueryParameters : PaginatedQueryParameters +{ + public string? SearchTerm { get; set; } +} \ No newline at end of file diff --git a/src/Application/Common/Models/Dtos/Logging/LockerLogDto.cs b/src/Application/Common/Models/Dtos/Logging/LockerLogDto.cs new file mode 100644 index 00000000..b37cf09e --- /dev/null +++ b/src/Application/Common/Models/Dtos/Logging/LockerLogDto.cs @@ -0,0 +1,25 @@ +using Application.Common.Mappings; +using Application.Common.Models.Dtos.Physical; +using Application.Users.Queries; +using AutoMapper; +using Domain.Entities.Logging; + +namespace Application.Common.Models.Dtos.Logging; + +public class LockerLogDto : IMapFrom +{ + public Guid Id { get; set; } + public string Action { get; set; } = null!; + public LockerDto? Object { get; set; } + public DateTime Time { get; set; } + public UserDto User { get; set; } = null!; + + public void Mapping(Profile profile) + { + profile.CreateMap() + .ForMember( dest => dest.Time, + opt => opt.MapFrom( src => src.Time.ToDateTimeUnspecified())) + .ForMember(dest => dest.Object, + opt => opt.MapFrom( src => src.Object)); + } +} \ No newline at end of file diff --git a/src/Application/Lockers/Queries/GetAllLockerLogsPaginated.cs b/src/Application/Lockers/Queries/GetAllLockerLogsPaginated.cs new file mode 100644 index 00000000..b098fa14 --- /dev/null +++ b/src/Application/Lockers/Queries/GetAllLockerLogsPaginated.cs @@ -0,0 +1,68 @@ +using Application.Common.Extensions; +using Application.Common.Interfaces; +using Application.Common.Models; +using Application.Common.Models.Dtos.Logging; +using AutoMapper; +using MediatR; +using Microsoft.EntityFrameworkCore; + +namespace Application.Lockers.Queries; + +public class GetAllLockerLogsPaginated +{ + public record Query : IRequest> + { + public string? SearchTerm { get; init; } + public int? Page { get; init; } + public int? Size { get; init; } + public string? SortBy { get; init; } + public string? SortOrder { get; init; } + } + + public class QueryHandler : IRequestHandler> + { + private readonly IApplicationDbContext _context; + private readonly IMapper _mapper; + + public QueryHandler(IApplicationDbContext context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task> Handle(Query request, CancellationToken cancellationToken) + { + var logs = _context.LockerLogs + .Include(x => x.Object) + .Include(x => x.User) + .ThenInclude(x => x.Department) + .AsQueryable(); + + if (!(request.SearchTerm is null || request.SearchTerm.Trim().Equals(string.Empty))) + { + logs = logs.Where(x => + x.Action.Trim().ToLower().Contains(request.SearchTerm.Trim().ToLower())); + } + + var sortBy = request.SortBy; + if (sortBy is null || !sortBy.MatchesPropertyName()) + { + sortBy = nameof(LockerLogDto.Time); + } + + var sortOrder = request.SortOrder ?? "dsc"; + var pageNumber = request.Page is null or <= 0 ? 1 : request.Page; + var sizeNumber = request.Size is null or <= 0 ? 5 : request.Size; + + var count = await logs.CountAsync(cancellationToken); + var list = await logs + .Paginate(pageNumber.Value, sizeNumber.Value) + .OrderByCustom(sortBy, sortOrder) + .ToListAsync(cancellationToken); + + var result = _mapper.Map>(list); + + return new PaginatedList(result, count, pageNumber.Value, sizeNumber.Value); + } + } +} \ No newline at end of file diff --git a/src/Application/Lockers/Queries/GetLockerLogById.cs b/src/Application/Lockers/Queries/GetLockerLogById.cs new file mode 100644 index 00000000..8930e90b --- /dev/null +++ b/src/Application/Lockers/Queries/GetLockerLogById.cs @@ -0,0 +1,43 @@ +using Application.Common.Interfaces; +using Application.Common.Models.Dtos.Logging; +using AutoMapper; +using MediatR; +using Microsoft.EntityFrameworkCore; + +namespace Application.Lockers.Queries; + +public class GetLockerLogById +{ + public record Query : IRequest + { + public Guid LogId { get; init; } + } + + public class QueryHandler : IRequestHandler + { + private readonly IApplicationDbContext _context; + private readonly IMapper _mapper; + + public QueryHandler(IApplicationDbContext context, IMapper mapper) + { + _context = context; + _mapper = mapper; + } + + public async Task Handle(Query request, CancellationToken cancellationToken) + { + var log = await _context.LockerLogs + .Include(x => x.Object) + .Include(x => x.User) + .ThenInclude(x => x.Department) + .FirstOrDefaultAsync(x => x.Id.Equals(request.LogId), cancellationToken); + + if (log is null) + { + throw new KeyNotFoundException("Log does not exist."); + } + + return _mapper.Map(log); + } + } +} \ No newline at end of file From c798705326414f3252930651a2e3c1ed3a88a4c9 Mon Sep 17 00:00:00 2001 From: StarryFolf Date: Wed, 14 Jun 2023 09:39:04 +0700 Subject: [PATCH 2/4] refactoring --- src/Application/Lockers/Queries/GetAllLockerLogsPaginated.cs | 1 + src/Application/Lockers/Queries/GetLockerLogById.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Application/Lockers/Queries/GetAllLockerLogsPaginated.cs b/src/Application/Lockers/Queries/GetAllLockerLogsPaginated.cs index b098fa14..a917796a 100644 --- a/src/Application/Lockers/Queries/GetAllLockerLogsPaginated.cs +++ b/src/Application/Lockers/Queries/GetAllLockerLogsPaginated.cs @@ -34,6 +34,7 @@ public async Task> Handle(Query request, Cancellatio { var logs = _context.LockerLogs .Include(x => x.Object) + .ThenInclude(x => x!.Room) .Include(x => x.User) .ThenInclude(x => x.Department) .AsQueryable(); diff --git a/src/Application/Lockers/Queries/GetLockerLogById.cs b/src/Application/Lockers/Queries/GetLockerLogById.cs index 8930e90b..33380268 100644 --- a/src/Application/Lockers/Queries/GetLockerLogById.cs +++ b/src/Application/Lockers/Queries/GetLockerLogById.cs @@ -28,6 +28,7 @@ public async Task Handle(Query request, CancellationToken cancella { var log = await _context.LockerLogs .Include(x => x.Object) + .ThenInclude(x => x!.Room) .Include(x => x.User) .ThenInclude(x => x.Department) .FirstOrDefaultAsync(x => x.Id.Equals(request.LogId), cancellationToken); From 6d059e90bf1a7a7c687ca37cec45016edab615dc Mon Sep 17 00:00:00 2001 From: StarryFolf Date: Wed, 14 Jun 2023 09:57:44 +0700 Subject: [PATCH 3/4] refactoring --- src/Api/Controllers/LockersController.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Api/Controllers/LockersController.cs b/src/Api/Controllers/LockersController.cs index b1543c4c..5952c14e 100644 --- a/src/Api/Controllers/LockersController.cs +++ b/src/Api/Controllers/LockersController.cs @@ -190,7 +190,7 @@ public async Task>> Update([FromRoute] Guid locke [HttpGet("logs")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] - public async Task>>> GetAllFolderLogs( + public async Task>>> GetAllLockerLogs( [FromQuery] GetAllLogsPaginatedQueryParameters queryParameters) { var query = new GetAllLockerLogsPaginated.Query() @@ -215,7 +215,7 @@ public async Task>>> GetAllFolde [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task>> GetUserLogById([FromRoute] Guid logId) + public async Task>> GetLockerLogById([FromRoute] Guid logId) { var query = new GetLockerLogById.Query() { From 1cd37e4b7ab427e242691ac0e62bcbfb9deb89e8 Mon Sep 17 00:00:00 2001 From: StarryFolf <67864500+StarryFolf@users.noreply.github.com> Date: Wed, 14 Jun 2023 10:19:44 +0700 Subject: [PATCH 4/4] Update GetAllLockerLogsPaginated.cs --- src/Application/Lockers/Queries/GetAllLockerLogsPaginated.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Application/Lockers/Queries/GetAllLockerLogsPaginated.cs b/src/Application/Lockers/Queries/GetAllLockerLogsPaginated.cs index a917796a..475bdf84 100644 --- a/src/Application/Lockers/Queries/GetAllLockerLogsPaginated.cs +++ b/src/Application/Lockers/Queries/GetAllLockerLogsPaginated.cs @@ -34,9 +34,6 @@ public async Task> Handle(Query request, Cancellatio { var logs = _context.LockerLogs .Include(x => x.Object) - .ThenInclude(x => x!.Room) - .Include(x => x.User) - .ThenInclude(x => x.Department) .AsQueryable(); if (!(request.SearchTerm is null || request.SearchTerm.Trim().Equals(string.Empty))) @@ -66,4 +63,4 @@ public async Task> Handle(Query request, Cancellatio return new PaginatedList(result, count, pageNumber.Value, sizeNumber.Value); } } -} \ No newline at end of file +}