feat(sales): agregar búsqueda paginada de Delivery Note (search endpoint + DTO resumen) closes #27 #28

Merged
leandro merged 1 commits from feature/leandro/27-deliverynote-search into master 2026-03-21 02:04:53 +00:00
7 changed files with 203 additions and 2 deletions

View File

@ -1,4 +1,5 @@
using Domain.Dtos.Sales;
using Domain.Generics;
/// <summary>
/// Servicio de dominio para la gestión de consultas de Delivery Note (Remito Ventas).
@ -6,6 +7,21 @@ using Domain.Dtos.Sales;
/// </summary>
public interface IDeliveryNoteDom
{
/// <summary>
/// Busca Delivery Notes con filtros y paginación.
/// </summary>
Task<PagedResult<DeliveryNoteSummaryDto>> SearchAsync(
int? customerId,
string? customerText,
string? deliveryNoteNumber,
int? quoteId,
string? quoteNumber,
DateTime? issueDateFrom,
DateTime? issueDateTo,
string? status,
int page = 1,
int pageSize = 50);
/// <summary>
/// Obtiene un Delivery Note por su identificador único.
/// </summary>

View File

@ -1,5 +1,6 @@
using Core.Interfaces;
using Domain.Dtos.Sales;
using Domain.Generics;
using Models.Interfaces;
namespace Core.Services
@ -8,6 +9,34 @@ namespace Core.Services
{
private readonly IPhSDeliveryNoteRepository _deliveryNoteRepository = deliveryNoteRepository;
public Task<PagedResult<DeliveryNoteSummaryDto>> SearchAsync(
int? customerId,
string? customerText,
string? deliveryNoteNumber,
int? quoteId,
string? quoteNumber,
DateTime? issueDateFrom,
DateTime? issueDateTo,
string? status,
int page = 1,
int pageSize = 50)
{
page = page <= 0 ? 1 : page;
pageSize = pageSize <= 0 ? 50 : pageSize;
return _deliveryNoteRepository.SearchAsync(
customerId,
string.IsNullOrWhiteSpace(customerText) ? null : customerText.Trim(),
string.IsNullOrWhiteSpace(deliveryNoteNumber) ? null : deliveryNoteNumber.Trim(),
quoteId,
string.IsNullOrWhiteSpace(quoteNumber) ? null : quoteNumber.Trim(),
issueDateFrom,
issueDateTo,
string.IsNullOrWhiteSpace(status) ? null : status.Trim(),
page,
pageSize);
}
public Task<DeliveryNoteDto?> GetDtoByIdAsync(int id)
{
if (id <= 0)

View File

@ -0,0 +1,18 @@
namespace Domain.Dtos.Sales
{
public class DeliveryNoteSummaryDto
{
public int Id { get; set; }
public string DeliveryNoteNumber { get; set; } = string.Empty;
public int? QuoteId { get; set; }
public string? QuoteNumber { get; set; }
public DateTime IssueDate { get; set; }
public int CustomerId { get; set; }
public string CustomerName { get; set; } = string.Empty;
public string Status { get; set; } = string.Empty;
public string? Observations { get; set; }
public int PrintCount { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? ModifiedAt { get; set; }
}
}

View File

@ -0,0 +1,14 @@
namespace Domain.Generics
{
public class DeliveryNoteSearchParams : PagedRequest
{
public string? DeliveryNoteNumber { get; set; }
public int? CustomerId { get; set; }
public string? CustomerText { get; set; }
public int? QuoteId { get; set; }
public string? QuoteNumber { get; set; }
public DateTime? IssueDateFrom { get; set; }
public DateTime? IssueDateTo { get; set; }
public string? Status { get; set; }
}
}

View File

@ -1,9 +1,22 @@
using Domain.Dtos.Sales;
using Domain.Dtos.Sales;
using Domain.Generics;
namespace Models.Interfaces
{
public interface IPhSDeliveryNoteRepository
{
Task<PagedResult<DeliveryNoteSummaryDto>> SearchAsync(
int? customerId,
string? customerText,
string? deliveryNoteNumber,
int? quoteId,
string? quoteNumber,
DateTime? issueDateFrom,
DateTime? issueDateTo,
string? status,
int page = 1,
int pageSize = 50);
Task<DeliveryNoteDto?> GetDtoByIdAsync(int id);
Task<DeliveryNoteDto?> GetDtoByDeliveryNoteNumberAsync(string deliveryNoteNumber);
Task<IEnumerable<DeliveryNoteDto>> GetDtosByQuoteIdAsync(int quoteId);

View File

@ -1,5 +1,7 @@
using Domain.Dtos.Sales;
using Domain.Generics;
using Microsoft.EntityFrameworkCore;
using Models.Helpers;
using Models.Interfaces;
using Models.Models;
@ -9,6 +11,77 @@ namespace Models.Repositories
{
private readonly PhronCareOperationsHubContext _context = context;
public async Task<PagedResult<DeliveryNoteSummaryDto>> SearchAsync(
int? customerId,
string? customerText,
string? deliveryNoteNumber,
int? quoteId,
string? quoteNumber,
DateTime? issueDateFrom,
DateTime? issueDateTo,
string? status,
int page = 1,
int pageSize = 50)
{
var query = _context.PhSDeliveryNotes
.AsNoTracking()
.Include(x => x.Customer)
.Include(x => x.Quote)
.AsQueryable();
if (customerId.HasValue)
query = query.Where(x => x.CustomerId == customerId.Value);
else if (!string.IsNullOrWhiteSpace(customerText))
query = query.Where(x => x.Customer.Name.Contains(customerText));
if (!string.IsNullOrWhiteSpace(deliveryNoteNumber))
query = query.Where(x => x.Deliverynotenumber.Contains(deliveryNoteNumber));
if (quoteId.HasValue)
query = query.Where(x => x.QuoteId == quoteId.Value);
else if (!string.IsNullOrWhiteSpace(quoteNumber))
query = query.Where(x => x.Quote != null && x.Quote.Quotenumber.Contains(quoteNumber));
if (issueDateFrom.HasValue)
query = query.Where(x => x.Issuedate >= issueDateFrom.Value);
if (issueDateTo.HasValue)
query = query.Where(x => x.Issuedate <= issueDateTo.Value);
if (!string.IsNullOrWhiteSpace(status))
query = query.Where(x => x.Status == status);
query = query
.OrderByDescending(x => x.Issuedate)
.ThenByDescending(x => x.Id);
var pagedEntities = await query.ToPagedResultAsync(page, pageSize);
var dtos = pagedEntities.Items.Select(x => new DeliveryNoteSummaryDto
{
Id = x.Id,
DeliveryNoteNumber = x.Deliverynotenumber,
QuoteId = x.QuoteId,
QuoteNumber = x.Quote?.Quotenumber,
IssueDate = x.Issuedate,
CustomerId = x.CustomerId,
CustomerName = x.Customer?.Name ?? string.Empty,
Status = x.Status,
Observations = x.Observations,
PrintCount = x.Printcount,
CreatedAt = x.Createdat,
ModifiedAt = x.Modifiedat
}).ToList();
return new PagedResult<DeliveryNoteSummaryDto>
{
Items = dtos,
TotalItems = pagedEntities.TotalItems,
Page = pagedEntities.Page,
PageSize = pagedEntities.PageSize
};
}
public async Task<DeliveryNoteDto?> GetDtoByIdAsync(int id)
{
var entity = await _context.PhSDeliveryNotes

View File

@ -1,4 +1,6 @@
using Domain.Dtos.Sales;
using Core.Interfaces;
using Domain.Dtos.Sales;
using Domain.Generics;
using Microsoft.AspNetCore.Mvc;
using System.Reflection;
@ -15,6 +17,42 @@ namespace phronCare.API.Controllers.Sales
_deliveryNoteService = deliveryNoteService ?? throw new ArgumentNullException(nameof(deliveryNoteService));
}
[HttpGet("search")]
public async Task<ActionResult<PagedResult<DeliveryNoteSummaryDto>>> Search(
[FromQuery] int? customerId,
[FromQuery] string? customerText,
[FromQuery] string? deliveryNoteNumber,
[FromQuery] int? quoteId,
[FromQuery] string? quoteNumber,
[FromQuery] DateTime? issueDateFrom,
[FromQuery] DateTime? issueDateTo,
[FromQuery] string? status,
[FromQuery] int page = 1,
[FromQuery] int pageSize = 50)
{
try
{
var result = await _deliveryNoteService.SearchAsync(
customerId,
customerText,
deliveryNoteNumber,
quoteId,
quoteNumber,
issueDateFrom,
issueDateTo,
status,
page,
pageSize);
return Ok(result);
}
catch (Exception ex)
{
var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
return StatusCode(500, $"{methodName} Message: {ex.Message}");
}
}
[HttpGet("{id:int}")]
public async Task<ActionResult<DeliveryNoteDto>> GetById(int id)
{