211 lines
7.7 KiB
C#
Raw Permalink Normal View History

2025-05-16 17:19:40 -03:00
using Microsoft.AspNetCore.Mvc;
using Documents.Models;
using Domain.Dtos;
2025-05-13 12:08:38 -03:00
using Domain.Entities;
2025-04-27 02:19:29 -03:00
using Domain.Generics;
using System.Reflection;
2025-05-16 17:19:40 -03:00
using Documents.Interfaces;
2025-09-04 18:15:15 -03:00
using Core.Interfaces;
2025-04-27 02:19:29 -03:00
namespace phronCare.API.Controllers.Sales
{
[Route("api/[controller]")]
[ApiController]
public class QuoteController : ControllerBase
{
2025-05-16 17:19:40 -03:00
private readonly IDocumentTemplateService _documentTemplateService;
2025-04-27 02:19:29 -03:00
private readonly IQuoteDom _quoteService;
2025-05-16 17:19:40 -03:00
public QuoteController(IDocumentTemplateService documentTemplateService, IQuoteDom quoteService)
2025-04-27 02:19:29 -03:00
{
2025-05-16 17:19:40 -03:00
_documentTemplateService = documentTemplateService ??
throw new ArgumentNullException(nameof(documentTemplateService)); ;
_quoteService = quoteService ??
throw new ArgumentNullException(nameof(quoteService));
2025-04-27 02:19:29 -03:00
}
#region Obtener Presupuestos
2025-05-13 12:08:38 -03:00
/// <summary>
/// Busca presupuestos con filtros de texto libre o por ID, paginados.
/// </summary>
2025-04-27 02:19:29 -03:00
[HttpGet("search")]
2025-05-13 12:08:38 -03:00
public async Task<ActionResult<PagedResult<QuoteDto>>> Search(
2025-04-27 02:19:29 -03:00
[FromQuery] int? customerId,
2025-05-13 12:08:38 -03:00
[FromQuery] string? customerText,
2025-04-27 02:19:29 -03:00
[FromQuery] string? quoteNumber,
[FromQuery] int? professionalId,
2025-05-13 12:08:38 -03:00
[FromQuery] string? professionalText,
2025-04-27 02:19:29 -03:00
[FromQuery] int? institutionId,
2025-05-13 12:08:38 -03:00
[FromQuery] string? institutionText,
2025-04-27 02:19:29 -03:00
[FromQuery] int? patientId,
2025-05-13 12:08:38 -03:00
[FromQuery] string? patientText,
2025-04-27 02:19:29 -03:00
[FromQuery] DateTime? issueDateFrom,
[FromQuery] DateTime? issueDateTo,
[FromQuery] string? status,
[FromQuery] int page = 1,
[FromQuery] int pageSize = 50)
{
try
{
2025-05-13 12:08:38 -03:00
var result = await _quoteService.SearchAsync(
2025-04-27 02:19:29 -03:00
customerId,
2025-05-13 12:08:38 -03:00
customerText,
2025-04-27 02:19:29 -03:00
quoteNumber,
professionalId,
2025-05-13 12:08:38 -03:00
professionalText,
2025-04-27 02:19:29 -03:00
institutionId,
2025-05-13 12:08:38 -03:00
institutionText,
2025-04-27 02:19:29 -03:00
patientId,
2025-05-13 12:08:38 -03:00
patientText,
2025-04-27 02:19:29 -03:00
issueDateFrom,
issueDateTo,
status,
page,
pageSize);
return Ok(result);
}
catch (Exception ex)
{
var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
2025-05-13 12:08:38 -03:00
// Log exception as needed...
2025-04-27 02:19:29 -03:00
return StatusCode(500, $"{methodName} Message: {ex.Message}");
}
}
2025-05-13 12:08:38 -03:00
2025-05-29 19:21:57 -03:00
/// <summary>
/// Obtiene un presupuesto completo por su ID.
/// </summary>
[HttpGet("{id}")]
public async Task<ActionResult<QuoteDto>> GetById(int id)
{
try
{
var quote = await _quoteService.GetDtoByIdAsync(id);
if (quote == null)
return NotFound($"Presupuesto con ID {id} no encontrado.");
return Ok(quote);
}
catch (Exception ex)
{
var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
return StatusCode(500, $"{methodName} Message: {ex.Message}");
}
}
2025-08-18 00:47:37 -03:00
/// <summary>
/// Devuelve un presupuesto DTO con información básica a partir del número de presupuesto.
/// </summary>
[HttpGet("summary/{quoteNumber}")]
public async Task<ActionResult<QuoteDto>> GetHeaderDtoByQuoteNumber(string quoteNumber)
{
try
{
var dto = await _quoteService.GetDtoByQuoteNumberAsync(quoteNumber);
if (dto == null)
return NotFound($"No se encontró un presupuesto con el número: {quoteNumber}");
return Ok(dto);
}
catch (Exception ex)
{
var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
return StatusCode(500, $"{methodName} Message: {ex.Message}");
}
}
2025-09-04 18:15:15 -03:00
#endregion
2025-05-29 19:21:57 -03:00
2025-08-18 00:47:37 -03:00
/// <summary>
/// Genera y devuelve un archivo PDF correspondiente al presupuesto especificado por su ID.
/// </summary>
2025-05-17 00:23:45 -03:00
[HttpGet("{id}/pdf")]
2025-05-16 17:19:40 -03:00
public async Task<IActionResult> GetQuotePdf(int id)
{
var quote = await _quoteService.GetDtoByIdAsync(id);
2025-05-13 12:08:38 -03:00
2025-05-16 17:19:40 -03:00
if (quote == null)
return NotFound($"Presupuesto con ID {id} no encontrado.");
2025-05-13 12:08:38 -03:00
2025-05-16 17:19:40 -03:00
var pdfBytes = await _documentTemplateService.GenerateDocumentAsync(new DocumentGenerationRequest
{
2025-09-04 18:15:15 -03:00
Model = quote,
DocumentType = DocumentType.Quote
2025-05-16 17:19:40 -03:00
});
2025-05-13 12:08:38 -03:00
2025-05-16 17:19:40 -03:00
return File(pdfBytes, "application/pdf", $"Presupuesto_{quote.Quotenumber}.pdf");
}
2025-09-11 22:41:46 -03:00
[HttpPost("exportfiltered")]
public async Task<IActionResult> ExportFiltered([FromBody] QuoteSearchParams searchParams)
{
try
{
var file = await _quoteService.ExportFilteredToExcelAsync(searchParams);
return File(file,
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"Expediciones.xlsx");
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
2025-05-06 15:58:35 -03:00
2025-05-06 21:00:03 -03:00
#region Endpoint de emision de presupuesto (encabezado + detalles + roles + ajustes + impuestos)
[HttpPost("createfull")]
public async Task<IActionResult> CreateFullQuote([FromBody] CreateFullQuoteRequest request)
2025-05-06 21:00:03 -03:00
{
try
{
// Validamos que el request y el objeto Quote no sean nulos
if (request == null || request.Quote == null)
return BadRequest("El payload no puede contener elementos nulos.");
2025-05-06 21:00:03 -03:00
// Desempaquetamos los datos
var quote = request.Quote;
var formSeriesId = request.FormSeriesId;
// Llamada al servicio de negocio
2025-05-18 03:21:48 -03:00
(int quoteId, string quoteNumber) = await _quoteService.CreateFullQuoteAsync(request.Quote, request.FormSeriesId);
// Devolvemos el número generado
2025-05-18 03:21:48 -03:00
return Ok(new { Success = true, Id = quoteId, QuoteNumber = quoteNumber });
2025-05-06 21:00:03 -03:00
}
catch (ArgumentNullException ex)
{
return BadRequest($"Validación fallida: {ex.Message}");
}
catch (InvalidOperationException ex)
{
return BadRequest($"Error de negocio: {ex.Message}");
}
catch (Exception ex)
{
return StatusCode(500, $"Ocurrió un error interno: {ex.Message}");
2025-05-06 21:00:03 -03:00
}
}
public class CreateFullQuoteRequest
{
public EQuoteHeader Quote { get; set; } = default!;
public int FormSeriesId { get; set; }
}
2025-05-06 21:00:03 -03:00
#endregion
2025-05-16 17:19:40 -03:00
2025-05-29 19:21:57 -03:00
#region Autorizacion de presupuestos
[HttpPost("authorize")]
public async Task<IActionResult> AuthorizeQuote([FromBody] QuoteAuthorizationRequest request)
{
if (request == null || request.Items == null)
2025-05-29 21:16:55 -03:00
return BadRequest("No se recibió información válida para autorizar.");
2025-05-29 19:21:57 -03:00
var result = await _quoteService.AuthorizeQuoteAsync(request.QuoteId, request.Items);
2025-05-16 17:19:40 -03:00
2025-05-29 19:21:57 -03:00
return result
? Ok(new { success = true, message = "Presupuesto procesado correctamente." })
2025-05-29 21:16:55 -03:00
: BadRequest(new { success = false, message = "No se pudo autorizar el presupuesto." });
2025-05-29 19:21:57 -03:00
}
#endregion
2025-04-27 02:19:29 -03:00
}
2025-05-06 15:58:35 -03:00
}