From ce7b239bddd509e89f50c81e0a5080b60ab023a4 Mon Sep 17 00:00:00 2001 From: amiralirahimii Date: Sat, 31 Aug 2024 15:29:46 +0330 Subject: [PATCH] feat: paginate response of get-all-transactions api --- src/Application/DTOs/PaginatedList.cs | 21 +++++++++++++++++++ .../Repositories/ITransactionRepository.cs | 3 ++- .../Services/ITransactionService.cs | 2 +- .../DomainService/TransactionService.cs | 13 ++++++++---- .../SharedService/PaginatorService.cs | 16 ++++++++++++++ .../Repositories/TransactionRepository.cs | 13 ++++++++++-- src/Web/Controllers/TransactionsController.cs | 4 ++-- src/Web/Mappers/TransactionMapper.cs | 10 ++++++--- 8 files changed, 69 insertions(+), 13 deletions(-) create mode 100644 src/Application/DTOs/PaginatedList.cs create mode 100644 src/Application/Services/SharedService/PaginatorService.cs diff --git a/src/Application/DTOs/PaginatedList.cs b/src/Application/DTOs/PaginatedList.cs new file mode 100644 index 0000000..3643356 --- /dev/null +++ b/src/Application/DTOs/PaginatedList.cs @@ -0,0 +1,21 @@ +namespace Application.DTOs; + +public class PaginatedList +{ + public List Items { get; } + public int TotalCount { get; } + public int PageNumber { get; } + public int PageSize { get; } + public int TotalPages => (int)Math.Ceiling(TotalCount / (double)PageSize); + + public PaginatedList(List items, int count, int pageNumber, int pageSize) + { + Items = items; + TotalCount = count; + PageNumber = pageNumber; + PageSize = pageSize; + } + + public bool HasPreviousPage => PageNumber > 1; + public bool HasNextPage => PageNumber < TotalPages; +} diff --git a/src/Application/Interfaces/Repositories/ITransactionRepository.cs b/src/Application/Interfaces/Repositories/ITransactionRepository.cs index 684955e..00d990a 100644 --- a/src/Application/Interfaces/Repositories/ITransactionRepository.cs +++ b/src/Application/Interfaces/Repositories/ITransactionRepository.cs @@ -5,8 +5,9 @@ namespace Application.Interfaces.Repositories; public interface ITransactionRepository { Task CreateBulkAsync(List transactions); - Task> GetAllTransactions(); + Task> GetAllTransactions(int skip, int take); Task> GetBySourceAccountId(long accountId); Task> GetByDestinationAccountId(long accountId); Task> GetAllIdsAsync(); + Task CountAllTransactionsAsync(); } \ No newline at end of file diff --git a/src/Application/Interfaces/Services/ITransactionService.cs b/src/Application/Interfaces/Services/ITransactionService.cs index fa26ab5..4fb7111 100644 --- a/src/Application/Interfaces/Services/ITransactionService.cs +++ b/src/Application/Interfaces/Services/ITransactionService.cs @@ -7,6 +7,6 @@ namespace Application.Interfaces.Services; public interface ITransactionService { Task AddTransactionsFromCsvAsync(string filePath); - Task>> GetAllTransactionsAsync(); + Task>> GetAllTransactionsAsync(int pageNumber, int pageSize); Task>> GetTransactionsByAccountIdAsync(long accountId); } \ No newline at end of file diff --git a/src/Application/Services/DomainService/TransactionService.cs b/src/Application/Services/DomainService/TransactionService.cs index 3cd71eb..fa01f53 100644 --- a/src/Application/Services/DomainService/TransactionService.cs +++ b/src/Application/Services/DomainService/TransactionService.cs @@ -39,16 +39,21 @@ public async Task AddTransactionsFromCsvAsync(string filePath) } } - public async Task>> GetAllTransactionsAsync() + public async Task>> GetAllTransactionsAsync(int pageNumber, int pageSize) { try { - var transactions = await _transactionRepository.GetAllTransactions(); - return Result>.Ok(transactions); + var skip = (pageNumber - 1) * pageSize; + var transactions = await _transactionRepository.GetAllTransactions(skip, pageSize); + var totalTransactions = await _transactionRepository.CountAllTransactionsAsync(); + + var paginatedTransactions = new PaginatedList(transactions, totalTransactions, pageNumber, pageSize); + + return Result>.Ok(paginatedTransactions); } catch (Exception ex) { - return Result>.Fail($"An error occurred: {ex.Message}"); + return Result>.Fail($"An error occurred: {ex.Message}"); } } diff --git a/src/Application/Services/SharedService/PaginatorService.cs b/src/Application/Services/SharedService/PaginatorService.cs new file mode 100644 index 0000000..d815110 --- /dev/null +++ b/src/Application/Services/SharedService/PaginatorService.cs @@ -0,0 +1,16 @@ +using Application.DTOs; + +namespace Application.Services.SharedService; + +public static class PaginatorService +{ + public static PaginatedList Paginate(this IEnumerable source, int pageNumber, int pageSize) + { + var sourceList = source as IList ?? source.ToList(); + + var count = sourceList.Count; + var items = sourceList.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToList(); + + return new PaginatedList(items, count, pageNumber, pageSize); + } +} \ No newline at end of file diff --git a/src/Infrastructure/Repositories/TransactionRepository.cs b/src/Infrastructure/Repositories/TransactionRepository.cs index edc5a6c..2eb34a8 100644 --- a/src/Infrastructure/Repositories/TransactionRepository.cs +++ b/src/Infrastructure/Repositories/TransactionRepository.cs @@ -19,9 +19,13 @@ public async Task CreateBulkAsync(List transactions) await _dbContext.SaveChangesAsync(); } - public async Task> GetAllTransactions() + public async Task> GetAllTransactions(int skip, int take) { - return await _dbContext.Transactions.ToListAsync(); + return await _dbContext.Transactions + .OrderBy(t => t.TransactionId) + .Skip(skip) + .Take(take) + .ToListAsync(); } public Task> GetBySourceAccountId(long accountId) @@ -44,4 +48,9 @@ public async Task> GetAllIdsAsync() .Select(a => a.TransactionId) .ToListAsync(); } + + public async Task CountAllTransactionsAsync() + { + return await _dbContext.Transactions.CountAsync(); + } } \ No newline at end of file diff --git a/src/Web/Controllers/TransactionsController.cs b/src/Web/Controllers/TransactionsController.cs index 3efb8d1..cb73c93 100644 --- a/src/Web/Controllers/TransactionsController.cs +++ b/src/Web/Controllers/TransactionsController.cs @@ -56,9 +56,9 @@ public async Task UploadTransactions([FromForm] IFormFile file) [ProducesResponseType(400)] [ProducesResponseType(401)] [ProducesResponseType(403)] - public async Task GetAllTransactions() + public async Task GetAllTransactions(int pageNumber = 1, int pageSize = 30) { - var allTransactions = await _transactionService.GetAllTransactionsAsync(); + var allTransactions = await _transactionService.GetAllTransactionsAsync(pageNumber, pageSize); if (!allTransactions.Succeed) { var errorResponse = Errors.New(nameof(GetAllTransactions), allTransactions.Message); diff --git a/src/Web/Mappers/TransactionMapper.cs b/src/Web/Mappers/TransactionMapper.cs index a84c72a..aaabd02 100644 --- a/src/Web/Mappers/TransactionMapper.cs +++ b/src/Web/Mappers/TransactionMapper.cs @@ -1,3 +1,4 @@ +using Application.DTOs; using Domain.Entities; using Web.DTOs.Transaction; @@ -17,10 +18,10 @@ public static TransactionDto ToTransactionDto(this Transaction transaction) Type = transaction.Type }; } - - public static List ToGotAllTransactionsDto(this List transactions) + + public static PaginatedList ToGotAllTransactionsDto(this PaginatedList transactions) { - return transactions.Select(transaction => new TransactionDto + var dtoItems = transactions.Items.Select(transaction => new TransactionDto { TransactionId = transaction.TransactionId, SourceAccountId = transaction.SourceAccountId, @@ -29,5 +30,8 @@ public static List ToGotAllTransactionsDto(this List(dtoItems, transactions.TotalCount, transactions.PageNumber, transactions.PageSize); } + } \ No newline at end of file