From 63915aa9806d43d060eedb4eb76f9f48c6cb0e84 Mon Sep 17 00:00:00 2001 From: leandro Date: Fri, 20 Mar 2026 23:03:46 -0300 Subject: [PATCH] =?UTF-8?q?feat(sales):=20agregar=20b=C3=BAsqueda=20pagina?= =?UTF-8?q?da=20de=20Delivery=20Note=20(search=20endpoint=20+=20DTO=20resu?= =?UTF-8?q?men)=20closes=20#27?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/Interfaces/IDeliveryNoteDom.cs | 16 ++++ Core/Services/DeliveryNoteService.cs | 29 ++++++++ Domain/Dtos/Sales/DeliveryNoteSummaryDto.cs | 18 +++++ Domain/Generics/DeliveryNoteSearchParams.cs | 14 ++++ .../Interfaces/IPhSDeliveryNoteRepository.cs | 15 +++- .../Repositories/PhSDeliveryNoteRepository.cs | 73 +++++++++++++++++++ .../Sales/DeliveryNoteController.cs | 40 +++++++++- 7 files changed, 203 insertions(+), 2 deletions(-) create mode 100644 Domain/Dtos/Sales/DeliveryNoteSummaryDto.cs create mode 100644 Domain/Generics/DeliveryNoteSearchParams.cs diff --git a/Core/Interfaces/IDeliveryNoteDom.cs b/Core/Interfaces/IDeliveryNoteDom.cs index ab69e37..e63f606 100644 --- a/Core/Interfaces/IDeliveryNoteDom.cs +++ b/Core/Interfaces/IDeliveryNoteDom.cs @@ -1,4 +1,5 @@ using Domain.Dtos.Sales; +using Domain.Generics; /// /// Servicio de dominio para la gestión de consultas de Delivery Note (Remito Ventas). @@ -6,6 +7,21 @@ using Domain.Dtos.Sales; /// public interface IDeliveryNoteDom { + /// + /// Busca Delivery Notes con filtros y paginación. + /// + Task> SearchAsync( + int? customerId, + string? customerText, + string? deliveryNoteNumber, + int? quoteId, + string? quoteNumber, + DateTime? issueDateFrom, + DateTime? issueDateTo, + string? status, + int page = 1, + int pageSize = 50); + /// /// Obtiene un Delivery Note por su identificador único. /// diff --git a/Core/Services/DeliveryNoteService.cs b/Core/Services/DeliveryNoteService.cs index e338989..6b4894b 100644 --- a/Core/Services/DeliveryNoteService.cs +++ b/Core/Services/DeliveryNoteService.cs @@ -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> 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 GetDtoByIdAsync(int id) { if (id <= 0) diff --git a/Domain/Dtos/Sales/DeliveryNoteSummaryDto.cs b/Domain/Dtos/Sales/DeliveryNoteSummaryDto.cs new file mode 100644 index 0000000..88128eb --- /dev/null +++ b/Domain/Dtos/Sales/DeliveryNoteSummaryDto.cs @@ -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; } + } +} diff --git a/Domain/Generics/DeliveryNoteSearchParams.cs b/Domain/Generics/DeliveryNoteSearchParams.cs new file mode 100644 index 0000000..e2e6bd6 --- /dev/null +++ b/Domain/Generics/DeliveryNoteSearchParams.cs @@ -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; } + } +} diff --git a/Models/Interfaces/IPhSDeliveryNoteRepository.cs b/Models/Interfaces/IPhSDeliveryNoteRepository.cs index fb1b342..77223da 100644 --- a/Models/Interfaces/IPhSDeliveryNoteRepository.cs +++ b/Models/Interfaces/IPhSDeliveryNoteRepository.cs @@ -1,9 +1,22 @@ -using Domain.Dtos.Sales; +using Domain.Dtos.Sales; +using Domain.Generics; namespace Models.Interfaces { public interface IPhSDeliveryNoteRepository { + Task> SearchAsync( + int? customerId, + string? customerText, + string? deliveryNoteNumber, + int? quoteId, + string? quoteNumber, + DateTime? issueDateFrom, + DateTime? issueDateTo, + string? status, + int page = 1, + int pageSize = 50); + Task GetDtoByIdAsync(int id); Task GetDtoByDeliveryNoteNumberAsync(string deliveryNoteNumber); Task> GetDtosByQuoteIdAsync(int quoteId); diff --git a/Models/Repositories/PhSDeliveryNoteRepository.cs b/Models/Repositories/PhSDeliveryNoteRepository.cs index ba1cd55..dcf0395 100644 --- a/Models/Repositories/PhSDeliveryNoteRepository.cs +++ b/Models/Repositories/PhSDeliveryNoteRepository.cs @@ -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> 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 + { + Items = dtos, + TotalItems = pagedEntities.TotalItems, + Page = pagedEntities.Page, + PageSize = pagedEntities.PageSize + }; + } + public async Task GetDtoByIdAsync(int id) { var entity = await _context.PhSDeliveryNotes diff --git a/phronCare.API/Controllers/Sales/DeliveryNoteController.cs b/phronCare.API/Controllers/Sales/DeliveryNoteController.cs index d63c5ea..345431f 100644 --- a/phronCare.API/Controllers/Sales/DeliveryNoteController.cs +++ b/phronCare.API/Controllers/Sales/DeliveryNoteController.cs @@ -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>> 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> GetById(int id) {