From 7b9553ad4e32c72270275402cc0ec6d13f51f9be Mon Sep 17 00:00:00 2001 From: SmartRootsSrl Date: Tue, 21 Jul 2026 10:41:12 +0200 Subject: [PATCH] feat: add GET /api/chart/underlying/{idUnderlyings} endpoint --- .../Controllers/ChartController.cs | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/CertReports.Syncfusion/Controllers/ChartController.cs b/CertReports.Syncfusion/Controllers/ChartController.cs index b141d56..fd104cf 100644 --- a/CertReports.Syncfusion/Controllers/ChartController.cs +++ b/CertReports.Syncfusion/Controllers/ChartController.cs @@ -21,17 +21,20 @@ public class ChartController : ControllerBase { private readonly IChartDataService _chartDataService; private readonly IChartDataServiceV2 _chartDataServiceV2; + private readonly IUnderlyingChartDataService _underlyingChartDataService; private readonly ILogger _logger; private readonly IConfiguration _configuration; public ChartController( IChartDataService chartDataService, IChartDataServiceV2 chartDataServiceV2, + IUnderlyingChartDataService underlyingChartDataService, ILogger logger, IConfiguration configuration) { _chartDataService = chartDataService; _chartDataServiceV2 = chartDataServiceV2; + _underlyingChartDataService = underlyingChartDataService; _logger = logger; _configuration = configuration; } @@ -175,6 +178,67 @@ public class ChartController : ControllerBase } } + /// + /// Endpoint standalone: grafico con solo la linea prezzo storico di UN sottostante, + /// identificato da IDUnderlyings — nessun contesto certificato (no strike/barriere/legenda). + /// Richiede SP cedlab_Chart_UnderlyingOnly nel DB. + /// Formati supportati: png (default), jpg/jpeg, pdf. Non supporta jpgEnc né ?save=true + /// (nessun alias-certificato applicabile a un sottostante puro). + /// + [HttpGet("underlying/{idUnderlyings:int}")] + public async Task GenerateChartUnderlying( + int idUnderlyings, + [FromQuery] int width = 1100, + [FromQuery] int height = 700, + [FromQuery] string format = "png") + { + if (idUnderlyings <= 0) + return BadRequest("IDUnderlyings non valido."); + + width = Math.Clamp(width, 400, 2000); + height = Math.Clamp(height, 300, 1500); + + try + { + var chartData = await _underlyingChartDataService.GetChartDataAsync(idUnderlyings); + + if (chartData == null || chartData.Points.Count == 0) + { + return NotFound(new + { + status = "KO", + message = $"Nessun dato per il grafico del sottostante {idUnderlyings}.", + }); + } + + bool isJpeg = format.Equals("jpg", StringComparison.OrdinalIgnoreCase) + || format.Equals("jpeg", StringComparison.OrdinalIgnoreCase); + + byte[] imgBytes = SkiaChartRendererV2.RenderSingleSeriesToPng(chartData, width, height, jpeg: isJpeg); + + if (format.Equals("pdf", StringComparison.OrdinalIgnoreCase)) + { + byte[] pdfBytes = WrapPngInPdf(imgBytes); + Response.Headers.Append("Content-Disposition", $"inline; filename=chart_underlying_{idUnderlyings}.pdf"); + return File(pdfBytes, "application/pdf"); + } + + if (isJpeg) + { + Response.Headers.Append("Content-Disposition", $"inline; filename=chart_underlying_{idUnderlyings}.jpg"); + return File(imgBytes, "image/jpeg"); + } + + Response.Headers.Append("Content-Disposition", $"inline; filename=chart_underlying_{idUnderlyings}.png"); + return File(imgBytes, "image/png"); + } + catch (Exception ex) + { + _logger.LogError(ex, "Errore generazione chart sottostante per IDUnderlyings {IDUnderlyings}", idUnderlyings); + return StatusCode(500, new { status = "KO", message = "Errore nella generazione del grafico sottostante." }); + } + } + /// /// Salva il JPEG su disco nei percorsi configurati in appsettings.json (ChartSettings). /// format=jpg/jpeg → SavePath/{isin}.jpg