Add Pagination in API Customer
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Successful in 5m23s

This commit is contained in:
Leandro Hernan Rojas 2025-04-06 01:19:47 -03:00
parent 8b8e66086b
commit 3962d889fd
8 changed files with 162 additions and 28 deletions

View File

@ -1,4 +1,5 @@
using Domain.Entities; using Domain.Entities;
using Domain.Generics;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -13,7 +14,7 @@ namespace Core.Interfaces
Task<bool> DeleteAsync(int id); Task<bool> DeleteAsync(int id);
Task<IEnumerable<ECustomer>> GetAllAsync(); Task<IEnumerable<ECustomer>> GetAllAsync();
Task<ECustomer?> GetByIdAsync(int id); Task<ECustomer?> GetByIdAsync(int id);
Task<IEnumerable<ECustomer>> SearchAsync(string? name, string? email, string? document); Task<PagedResult<ECustomer>> SearchAsync(string? name, string? email, string? document, int page = 1, int pageSize = 50);
Task<bool> UpdateAsync(ECustomer entity); Task<bool> UpdateAsync(ECustomer entity);
} }
} }

View File

@ -1,6 +1,7 @@
using System.Reflection; using System.Reflection;
using Core.Interfaces; using Core.Interfaces;
using Domain.Entities; using Domain.Entities;
using Domain.Generics;
using Models.Helpers; using Models.Helpers;
using Models.Interfaces; using Models.Interfaces;
using Models.Models; using Models.Models;
@ -45,11 +46,11 @@ namespace Core.Services
throw new NotImplementedException(); throw new NotImplementedException();
} }
public async Task<IEnumerable<ECustomer>> SearchAsync(string? name, string? email, string? document) public async Task<PagedResult<ECustomer>> SearchAsync(string? name, string? email, string? document, int page, int pageSize)
{ {
try try
{ {
return await _repository.SearchAsync(name, email, document); return await _repository.SearchAsync(name, email, document, page, pageSize);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -58,6 +59,9 @@ namespace Core.Services
} }
} }
public Task<bool> UpdateAsync(ECustomer entity) public Task<bool> UpdateAsync(ECustomer entity)
{ {
throw new NotImplementedException(); throw new NotImplementedException();

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Domain.Generics
{
public class PagedRequest
{
public int Page { get; set; } = 1; // Página actual (empieza en 1)
public int PageSize { get; set; } = 10; // Tamaño de página por defecto
}
}

View File

@ -0,0 +1,12 @@
namespace Domain.Generics
{
public class PagedResult<T>
{
public IEnumerable<T> Items { get; set; } = Enumerable.Empty<T>();
public int TotalItems { get; set; }
public int Page { get; set; }
public int PageSize { get; set; }
public int TotalPages => (int)Math.Ceiling((double)TotalItems / PageSize);
}
}

View File

@ -0,0 +1,33 @@
using Domain.Generics;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Models.Helpers
{
public static class PaginationExtensions
{
public static async Task<PagedResult<T>> ToPagedResultAsync<T>(
this IQueryable<T> query,
int page,
int pageSize)
{
var totalItems = await query.CountAsync();
var items = await query
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
return new PagedResult<T>
{
Items = items,
TotalItems = totalItems,
Page = page,
PageSize = pageSize
};
}
}
}

View File

@ -1,4 +1,5 @@
using Domain.Entities; using Domain.Entities;
using Domain.Generics;
using Models.Models; using Models.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -14,7 +15,12 @@ namespace Models.Interfaces
Task<bool> DeleteAsync(int id); Task<bool> DeleteAsync(int id);
Task<IEnumerable<ECustomer>> GetAllAsync(); Task<IEnumerable<ECustomer>> GetAllAsync();
Task<ECustomer?> GetByIdAsync(int id); Task<ECustomer?> GetByIdAsync(int id);
Task<IEnumerable<ECustomer>> SearchAsync(string? name, string? email, string? document); Task<PagedResult<ECustomer>> SearchAsync(
string? name,
string? email,
string? document,
int page,
int pageSize);
Task<bool> UpdateAsync(ECustomer entity); Task<bool> UpdateAsync(ECustomer entity);
} }
} }

View File

@ -1,4 +1,5 @@
using Domain.Entities; using Domain.Entities;
using Domain.Generics;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Models.Helpers; using Models.Helpers;
@ -36,48 +37,92 @@ namespace Models.Repositories
return customer != null ? EntityMapper.MapEntity<PhSCustomer, ECustomer>(customer) : null; return customer != null ? EntityMapper.MapEntity<PhSCustomer, ECustomer>(customer) : null;
} }
public async Task<IEnumerable<ECustomer>> SearchAsync(string? name, string? email, string? document) public async Task<PagedResult<ECustomer>> SearchAsync(
string? name, string? email, string? document,
int page = 1, int pageSize = 50)
{ {
var query = _context.PhSCustomers var query = _context.PhSCustomers
.Include(c => c.Accounttypes) .Include(c => c.Accounttypes)
.Include(c => c.PhSCustomerDocuments) .Include(c => c.PhSCustomerDocuments)
.Include(c => c.PhSCustomerAddresses) .Include(c => c.PhSCustomerAddresses)
.Take(100)
.AsQueryable(); .AsQueryable();
if (!string.IsNullOrWhiteSpace(name)) if (!string.IsNullOrWhiteSpace(name))
{ {
var loweredName = name.ToLower(); var lowered = name.ToLower();
query = query.Where(c => query = query.Where(c =>
c.Name.ToLower().Contains(loweredName) || c.Name.ToLower().Contains(lowered) ||
c.BusinessName.ToLower().Contains(loweredName)); c.BusinessName.ToLower().Contains(lowered));
}
if (!string.IsNullOrWhiteSpace(email))
{
var loweredEmail = email.ToLower();
query = query.Where(c =>
c.PhSCustomerAddresses.Any(a =>
a.Email.ToLower().Contains(loweredEmail)));
} }
if (!string.IsNullOrWhiteSpace(document) && document != "?") if (!string.IsNullOrWhiteSpace(document) && document != "?")
{ {
query = query.Where(c => query = query.Where(c =>
c.PhSCustomerDocuments.Any(a => c.PhSCustomerDocuments.Any(d =>
EF.Functions.Like(a.DocumentNumber, $"%{document}%"))); EF.Functions.Like(d.DocumentNumber, $"%{document}%")));
} }
var customers = await query.ToListAsync(); if (!string.IsNullOrWhiteSpace(email))
{
var lowered = email.ToLower();
query = query.Where(c =>
c.PhSCustomerAddresses.Any(a =>
a.Email.ToLower().Contains(lowered)));
}
Console.WriteLine($"VALOR RECIBIDO DE 'name': {name}"); var pagedEntities = await query.ToPagedResultAsync(page, pageSize);
Console.WriteLine($"VALOR RECIBIDO DE 'email': {email}");
Console.WriteLine($"VALOR RECIBIDO DE 'document': {document}");
return new PagedResult<ECustomer>
return customers.Select(EntityMapper.MapEntity<PhSCustomer, ECustomer>); {
Items = pagedEntities.Items.Select(EntityMapper.MapEntity<PhSCustomer, ECustomer>),
TotalItems = pagedEntities.TotalItems,
Page = pagedEntities.Page,
PageSize = pagedEntities.PageSize
};
} }
//public async Task<IEnumerable<ECustomer>> SearchAsync(string? name, string? email, string? document)
//{
// var query = _context.PhSCustomers
// .Include(c => c.Accounttypes)
// .Include(c => c.PhSCustomerDocuments)
// .Include(c => c.PhSCustomerAddresses)
// .Take(100)
// .AsQueryable();
// if (!string.IsNullOrWhiteSpace(name))
// {
// var loweredName = name.ToLower();
// query = query.Where(c =>
// c.Name.ToLower().Contains(loweredName) ||
// c.BusinessName.ToLower().Contains(loweredName));
// }
// if (!string.IsNullOrWhiteSpace(email))
// {
// var loweredEmail = email.ToLower();
// query = query.Where(c =>
// c.PhSCustomerAddresses.Any(a =>
// a.Email.ToLower().Contains(loweredEmail)));
// }
// if (!string.IsNullOrWhiteSpace(document) && document != "?")
// {
// query = query.Where(c =>
// c.PhSCustomerDocuments.Any(a =>
// EF.Functions.Like(a.DocumentNumber, $"%{document}%")));
// }
// var customers = await query.ToListAsync();
// Console.WriteLine($"VALOR RECIBIDO DE 'name': {name}");
// Console.WriteLine($"VALOR RECIBIDO DE 'email': {email}");
// Console.WriteLine($"VALOR RECIBIDO DE 'document': {document}");
// return customers.Select(EntityMapper.MapEntity<PhSCustomer, ECustomer>);
//}
public async Task<ECustomer> AddAsync(ECustomer entity) public async Task<ECustomer> AddAsync(ECustomer entity)
{ {
var customer = EntityMapper.MapEntity<ECustomer, PhSCustomer>(entity); var customer = EntityMapper.MapEntity<ECustomer, PhSCustomer>(entity);

View File

@ -14,7 +14,7 @@ namespace phronCare.API.Controllers.Sales
{ {
_customerService = customerService ?? throw new ArgumentNullException(nameof(customerService)); _customerService = customerService ?? throw new ArgumentNullException(nameof(customerService));
} }
[HttpGet("GetAll")] [HttpGet("all")]
public async Task<IActionResult> GetAll() public async Task<IActionResult> GetAll()
{ {
try try
@ -28,11 +28,16 @@ namespace phronCare.API.Controllers.Sales
} }
} }
[HttpGet("search")] [HttpGet("search")]
public async Task<IActionResult> Search([FromQuery] string? name, [FromQuery] string? email, [FromQuery] string? document) public async Task<IActionResult> Search(
[FromQuery] string? name,
[FromQuery] string? email,
[FromQuery] string? document,
[FromQuery] int page = 1,
[FromQuery] int pageSize = 50)
{ {
try try
{ {
var result = await _customerService.SearchAsync(name, email, document); var result = await _customerService.SearchAsync(name, email, document, page, pageSize);
return Ok(result); return Ok(result);
} }
catch (Exception ex) catch (Exception ex)
@ -41,6 +46,20 @@ namespace phronCare.API.Controllers.Sales
return StatusCode(500, $"{methodName} Message: {ex.Message}"); return StatusCode(500, $"{methodName} Message: {ex.Message}");
} }
} }
//[HttpGet("search")]
//public async Task<IActionResult> Search([FromQuery] string? name, [FromQuery] string? email, [FromQuery] string? document)
//{
// try
// {
// var result = await _customerService.SearchAsync(name, email, document);
// return Ok(result);
// }
// catch (Exception ex)
// {
// var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
// return StatusCode(500, $"{methodName} Message: {ex.Message}");
// }
//}
} }
} }