All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Successful in 21m48s
154 lines
6.0 KiB
C#
154 lines
6.0 KiB
C#
using Core.Interfaces.Stock;
|
|
using Documents.Interfaces;
|
|
using Documents.Models;
|
|
using Domain.Dtos.Stock;
|
|
using Domain.Entities;
|
|
using Domain.Generics;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using System.Reflection;
|
|
|
|
namespace phronCare.API.Controllers.Stock
|
|
{
|
|
[Route("api/[controller]")]
|
|
[ApiController]
|
|
public class ExpeditionController : ControllerBase
|
|
{
|
|
private readonly IExpeditionDom _expeditionService; // ← este es _expeditionService
|
|
private readonly IDocumentTemplateService _documentTemplateService;
|
|
|
|
public ExpeditionController(
|
|
IDocumentTemplateService documentTemplateService,
|
|
IExpeditionDom expeditionService)
|
|
{
|
|
_documentTemplateService = documentTemplateService
|
|
?? throw new ArgumentNullException(nameof(documentTemplateService));
|
|
_expeditionService = expeditionService
|
|
?? throw new ArgumentNullException(nameof(expeditionService));
|
|
}
|
|
/// <summary>
|
|
/// Busca expediciones con filtros y paginación.
|
|
/// Filtros: número, estado, fechas de emisión, ubicación (opcional).
|
|
/// </summary>
|
|
[HttpGet("search")]
|
|
public async Task<ActionResult<PagedResult<ExpeditionDto>>> Search(
|
|
[FromQuery] string? expeditionNumber,
|
|
[FromQuery] string? status,
|
|
[FromQuery] DateTime? issueDateFrom,
|
|
[FromQuery] DateTime? issueDateTo,
|
|
[FromQuery] int? locationId,
|
|
[FromQuery] int page = 1,
|
|
[FromQuery] int pageSize = 50)
|
|
{
|
|
try
|
|
{
|
|
var result = await _expeditionService.SearchAsync(
|
|
expeditionNumber,
|
|
status,
|
|
issueDateFrom,
|
|
issueDateTo,
|
|
locationId,
|
|
page,
|
|
pageSize
|
|
);
|
|
|
|
return Ok(result);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
|
|
return StatusCode(500, $"{methodName} Message: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
// GET /api/expedition/{id}
|
|
[HttpGet("{id:int}")]
|
|
[ProducesResponseType(typeof(ExpeditionDto), StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
public async Task<ActionResult<ExpeditionDto>> GetById(int id)
|
|
{
|
|
var dto = await _expeditionService.GetDtoByIdAsync(id);
|
|
if (dto is null) return NotFound($"Expedición con ID {id} no encontrada.");
|
|
return Ok(dto);
|
|
}
|
|
|
|
// (opcional) GET /api/expedition/summary/{expeditionNumber}
|
|
[HttpGet("summary/{expeditionNumber}")]
|
|
[ProducesResponseType(typeof(ExpeditionDto), StatusCodes.Status200OK)]
|
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
|
public async Task<ActionResult<ExpeditionDto>> GetByNumber(string expeditionNumber)
|
|
{
|
|
var dto = await _expeditionService.GetDtoByExpeditionNumberAsync(expeditionNumber);
|
|
if (dto is null) return NotFound($"No se encontró expedición {expeditionNumber}.");
|
|
return Ok(dto);
|
|
}
|
|
#region Endpoint de emision de expedicion (encabezado + detalles)
|
|
[HttpPost("createfull")]
|
|
public async Task<IActionResult> CreateFullExpedition([FromBody] CreateFullExpeditionRequest request)
|
|
{
|
|
try
|
|
{
|
|
if (request == null || request.Expedition == null)
|
|
return BadRequest("El payload no puede contener elementos nulos.");
|
|
|
|
// Delegamos al service, que ahora arma el grafo y llama al repo atómico
|
|
var (id, number) = await _expeditionService.CreateAndIssueAsync(
|
|
request.Expedition,
|
|
request.Expedition.PhLsmExpeditionDetails, // detalles vienen dentro, igual que en Quotes
|
|
request.FormSeriesId);
|
|
|
|
// <<< Simetría absoluta con QuoteController: objeto anónimo >>>
|
|
return Ok(new { Success = true, Id = id, ExpeditionNumber = number });
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
return BadRequest($"Error de negocio: {ex.Message}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return StatusCode(500, $"Ocurrió un error interno: {ex.Message}");
|
|
}
|
|
}
|
|
#endregion
|
|
/// <summary>
|
|
/// Genera y devuelve un archivo PDF correspondiente al presupuesto especificado por su ID.
|
|
/// </summary>
|
|
[HttpGet("{id}/pdf")]
|
|
public async Task<IActionResult> GetQuotePdf(int id)
|
|
{
|
|
var expedition = await _expeditionService.GetDtoByIdAsync(id);
|
|
|
|
if (expedition == null)
|
|
return NotFound($"Expedicion con ID {id} no encontrado.");
|
|
|
|
var pdfBytes = await _documentTemplateService.GenerateDocumentAsync(new DocumentGenerationRequest
|
|
{
|
|
Model = expedition,
|
|
DocumentType = DocumentType.Expedition
|
|
});
|
|
|
|
return File(pdfBytes, "application/pdf", $"Expedicion_{expedition.Expeditionnumber}.pdf");
|
|
}
|
|
[HttpPost("exportfiltered")]
|
|
|
|
public async Task<IActionResult> ExportFiltered([FromBody] ExpeditionSearchParams searchParams)
|
|
{
|
|
try
|
|
{
|
|
var file = await _expeditionService.ExportFilteredToExcelAsync(searchParams);
|
|
return File(file,
|
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
"Expediciones.xlsx");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return BadRequest(ex.Message);
|
|
}
|
|
}
|
|
}
|
|
public class CreateFullExpeditionRequest
|
|
{
|
|
public ELSExpeditionHeader Expedition { get; set; } = default!;
|
|
public int FormSeriesId { get; set; }
|
|
}
|
|
}
|