diff --git a/LTS/LTS.API/Common/DateTimeExtensions.cs b/LTS/LTS.API/Common/DateTimeExtensions.cs new file mode 100644 index 0000000..6fc9190 --- /dev/null +++ b/LTS/LTS.API/Common/DateTimeExtensions.cs @@ -0,0 +1,15 @@ +namespace LTS.API.Common; + +public static class DateTimeExtensions +{ + public static DateTime ToUtc(this DateTime dt) => + dt.Kind switch + { + DateTimeKind.Utc => dt, + DateTimeKind.Local => dt.ToUniversalTime(), + _ => DateTime.SpecifyKind(dt, DateTimeKind.Utc) + }; + + public static DateTime? ToUtc(this DateTime? dt) => + dt.HasValue ? dt.Value.ToUtc() : null; +} diff --git a/LTS/LTS.API/Common/Response/PagedResult.cs b/LTS/LTS.API/Common/Response/CasesPaginatedResult.cs similarity index 70% rename from LTS/LTS.API/Common/Response/PagedResult.cs rename to LTS/LTS.API/Common/Response/CasesPaginatedResult.cs index 472f8c1..3506d12 100644 --- a/LTS/LTS.API/Common/Response/PagedResult.cs +++ b/LTS/LTS.API/Common/Response/CasesPaginatedResult.cs @@ -1,11 +1,13 @@ namespace LTS.API.Common.Response { - public class PagedResult + public class CasesPaginatedResult { public List Items { get; set; } = []; public int TotalCount { get; set; } public int PageNumber { get; set; } public int PageSize { get; set; } public int TotalPages => (int)Math.Ceiling((double)TotalCount / PageSize); + public int PendingCount { get; set; } + public int FinalizedCount { get; set; } } } diff --git a/LTS/LTS.API/Features/CaseFeature/CaseController.cs b/LTS/LTS.API/Features/CaseFeature/CaseController.cs index 0b90f1b..f86ae9d 100644 --- a/LTS/LTS.API/Features/CaseFeature/CaseController.cs +++ b/LTS/LTS.API/Features/CaseFeature/CaseController.cs @@ -18,6 +18,7 @@ public class CaseController(IMediator mediator) : ControllerBase [HttpPost("Create")] public async Task CreateCase(CreateCaseCommand request, CancellationToken ct) { + request.OrganizationId = Guid.Parse(User.FindFirst("OrganizationId")?.Value!); var result = await _mediator.Send(request, ct); return StatusCode((int)result.Status, result); } diff --git a/LTS/LTS.API/Features/CaseFeature/Queries/GetCases/GetAllCasesQuery.cs b/LTS/LTS.API/Features/CaseFeature/Queries/GetCases/GetAllCasesQuery.cs index f669637..30c3aa1 100644 --- a/LTS/LTS.API/Features/CaseFeature/Queries/GetCases/GetAllCasesQuery.cs +++ b/LTS/LTS.API/Features/CaseFeature/Queries/GetCases/GetAllCasesQuery.cs @@ -3,11 +3,11 @@ namespace LTS.API.Features.CaseFeature.Queries.GetCases { - public record GetAllCasesQuery() : IRequest>> + public record GetAllCasesQuery() : IRequest>> { public Guid OrganizationId { get; set; } public int Page { get; set; } = 1; - public int PageSize { get; set; } = 20; + public int PageSize { get; set; } = 5; } } diff --git a/LTS/LTS.API/Features/CaseFeature/Queries/GetCases/GetCasesHandler.cs b/LTS/LTS.API/Features/CaseFeature/Queries/GetCases/GetCasesHandler.cs index 118c2f5..ed59bc9 100644 --- a/LTS/LTS.API/Features/CaseFeature/Queries/GetCases/GetCasesHandler.cs +++ b/LTS/LTS.API/Features/CaseFeature/Queries/GetCases/GetCasesHandler.cs @@ -1,6 +1,7 @@ using CloudinaryDotNet.Core; using LTS.API.Common.Response; using LTS.API.Domain.Entities; +using LTS.API.Domain.Enums; using LTS.API.Infrastructure.Persistence; using MediatR; using Microsoft.EntityFrameworkCore; @@ -8,11 +9,11 @@ namespace LTS.API.Features.CaseFeature.Queries.GetCases { public class GetCasesHandler(AppDbContext context) - : IRequestHandler>> + : IRequestHandler>> { private readonly AppDbContext _context = context; - public async Task>> Handle( + public async Task>> Handle( GetAllCasesQuery request, CancellationToken ct) { try @@ -21,15 +22,18 @@ public async Task>> Handle( var totalCount = await query.CountAsync(ct); if (totalCount == 0) - return ApiResponse>.Ok("Case Table is Empty"); + return ApiResponse>.Ok("Case Table is Empty"); + + var pendingCount = await query.CountAsync(c => c.Status == CaseStatus.Pending, ct); + var finalizedCount = await query.CountAsync(c => c.Status == CaseStatus.Finalized, ct); var cases = await FetchPageAsync(query, request, ct); - return ApiResponse>.Ok(ToPagedResult(cases, totalCount, request)); + return ApiResponse>.Ok(ToPagedResult(cases, totalCount,pendingCount,finalizedCount, request)); } catch (Exception ex) { - return ApiResponse> + return ApiResponse> .Fail($"Internal server error: {ex.Message}"); } } @@ -69,14 +73,16 @@ await query - private static PagedResult ToPagedResult( - List cases, int totalCount, GetAllCasesQuery request) => + private static CasesPaginatedResult ToPagedResult( + List cases, int totalCount,int pendingCount,int finalizedCount,GetAllCasesQuery request) => new() { Items = cases, TotalCount = totalCount, PageNumber = request.Page, - PageSize = request.PageSize + PageSize = request.PageSize, + PendingCount=pendingCount, + FinalizedCount=finalizedCount }; #endregion } diff --git a/LTS/LTS.API/Features/CaseFeature/Queries/SearchCases/SearchCasesHandler.cs b/LTS/LTS.API/Features/CaseFeature/Queries/SearchCases/SearchCasesHandler.cs index 802c450..dcafc24 100644 --- a/LTS/LTS.API/Features/CaseFeature/Queries/SearchCases/SearchCasesHandler.cs +++ b/LTS/LTS.API/Features/CaseFeature/Queries/SearchCases/SearchCasesHandler.cs @@ -7,7 +7,7 @@ namespace LTS.API.Features.CaseFeature.Queries.SearchCases { - public class SearchCasesHandler : IRequestHandler>> + public class SearchCasesHandler : IRequestHandler>> { private readonly AppDbContext _context; @@ -16,7 +16,7 @@ public SearchCasesHandler(AppDbContext context) _context = context; } - public async Task>> Handle(SearchCasesQuery request, CancellationToken cancellationToken) + public async Task>> Handle(SearchCasesQuery request, CancellationToken cancellationToken) { try { @@ -90,7 +90,7 @@ public async Task>> Handle(SearchCasesQuery )).ToListAsync(cancellationToken); // 8. RETURN PAGED RESPONSE - var pagedResponse = new PagedResult + var pagedResponse = new CasesPaginatedResult { Items = cases, PageNumber = request.PageNumber, @@ -98,11 +98,11 @@ public async Task>> Handle(SearchCasesQuery TotalCount = totalCount, }; - return ApiResponse>.Ok(pagedResponse); + return ApiResponse>.Ok(pagedResponse); } catch (Exception ex) { - return ApiResponse>.Fail($"Search failed: {ex.Message}"); + return ApiResponse>.Fail($"Search failed: {ex.Message}"); } } } diff --git a/LTS/LTS.API/Features/CaseFeature/Queries/SearchCases/SearchCasesQuery.cs b/LTS/LTS.API/Features/CaseFeature/Queries/SearchCases/SearchCasesQuery.cs index 5ab0695..33def2d 100644 --- a/LTS/LTS.API/Features/CaseFeature/Queries/SearchCases/SearchCasesQuery.cs +++ b/LTS/LTS.API/Features/CaseFeature/Queries/SearchCases/SearchCasesQuery.cs @@ -4,11 +4,11 @@ namespace LTS.API.Features.CaseFeature.Queries.SearchCases { - public class SearchCasesQuery : IRequest>> + public class SearchCasesQuery : IRequest>> { public string? SearchTerm { get; set; } public int PageNumber { get; set; } = 1; - public int PageSize { get; set; } = 20; + public int PageSize { get; set; } = 5; // Filters (optional) public string? Status { get; set; } diff --git a/LTS/LTS.API/Features/Followups/Commands/CommandFollowupMappings.cs b/LTS/LTS.API/Features/Followups/Commands/CommandFollowupMappings.cs index 5094921..68cbe71 100644 --- a/LTS/LTS.API/Features/Followups/Commands/CommandFollowupMappings.cs +++ b/LTS/LTS.API/Features/Followups/Commands/CommandFollowupMappings.cs @@ -1,4 +1,5 @@ -using LTS.API.Domain.Entities; +using LTS.API.Common; +using LTS.API.Domain.Entities; using LTS.API.Features.Followups.Commands.CreateFollowup; namespace LTS.API.Features.Followups.Commands @@ -11,8 +12,8 @@ public static Followup ToEntity(this CreateFollowupCommand command) { Id = Guid.NewGuid(), CaseId = command.CaseId, - HearingDate = DateTime.SpecifyKind(command.HearingDate, DateTimeKind.Utc), - NextHearingDate = command.NextHearingDate.HasValue ? DateTime.SpecifyKind(command.NextHearingDate.Value, DateTimeKind.Utc) : null, + HearingDate = command.HearingDate.ToUtc(), + NextHearingDate =command.NextHearingDate.ToUtc(), InterimOrder = command.InterimOrder, Decision = command.Decision, Remarks = command.Remarks, diff --git a/LTS/LTS.API/Features/Followups/Commands/UpdateFollowup/UpdateFollowupHandler.cs b/LTS/LTS.API/Features/Followups/Commands/UpdateFollowup/UpdateFollowupHandler.cs index b8cd1dd..b8d3970 100644 --- a/LTS/LTS.API/Features/Followups/Commands/UpdateFollowup/UpdateFollowupHandler.cs +++ b/LTS/LTS.API/Features/Followups/Commands/UpdateFollowup/UpdateFollowupHandler.cs @@ -1,4 +1,5 @@ -using LTS.API.Common.Response; +using LTS.API.Common; +using LTS.API.Common.Response; using LTS.API.Infrastructure.Persistence; using MediatR; @@ -19,8 +20,8 @@ public async Task> Handle(UpdateFollowupCommand request, Can if (followup is null) return ApiResponse.Fail("Followup not found."); - followup.HearingDate = request.HearingDate; - followup.NextHearingDate = request.NextHearingDate; + followup.HearingDate = request.HearingDate.ToUtc(); + followup.NextHearingDate = request.NextHearingDate.ToUtc(); followup.InterimOrder = request.InterimOrder; followup.Decision = request.Decision; followup.Remarks = request.Remarks;