feat: add expired certificate report branching in orchestrator
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -21,6 +21,7 @@ public class ReportOrchestrator : IReportOrchestrator
|
|||||||
private readonly IPdfMergerService _merger;
|
private readonly IPdfMergerService _merger;
|
||||||
private readonly IPdfCacheService _cache;
|
private readonly IPdfCacheService _cache;
|
||||||
private readonly ILogger<ReportOrchestrator> _logger;
|
private readonly ILogger<ReportOrchestrator> _logger;
|
||||||
|
private readonly ExpiredAnagraficaSectionRenderer _expiredAnagraficaRenderer;
|
||||||
|
|
||||||
public ReportOrchestrator(
|
public ReportOrchestrator(
|
||||||
ICertificateDataService dataService,
|
ICertificateDataService dataService,
|
||||||
@@ -28,7 +29,8 @@ public class ReportOrchestrator : IReportOrchestrator
|
|||||||
IChartSectionRenderer chartRenderer,
|
IChartSectionRenderer chartRenderer,
|
||||||
IPdfMergerService merger,
|
IPdfMergerService merger,
|
||||||
IPdfCacheService cache,
|
IPdfCacheService cache,
|
||||||
ILogger<ReportOrchestrator> logger)
|
ILogger<ReportOrchestrator> logger,
|
||||||
|
ExpiredAnagraficaSectionRenderer expiredAnagraficaRenderer)
|
||||||
{
|
{
|
||||||
_dataService = dataService;
|
_dataService = dataService;
|
||||||
_sectionRenderers = sectionRenderers;
|
_sectionRenderers = sectionRenderers;
|
||||||
@@ -36,13 +38,16 @@ public class ReportOrchestrator : IReportOrchestrator
|
|||||||
_merger = merger;
|
_merger = merger;
|
||||||
_cache = cache;
|
_cache = cache;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
_expiredAnagraficaRenderer = expiredAnagraficaRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<byte[]> GenerateReportAsync(string isin, bool showBranding = false)
|
public async Task<byte[]> GenerateReportAsync(string isin, bool showBranding = false)
|
||||||
{
|
{
|
||||||
// ── Cache check (chiave include branding) ─────────────────────────
|
// ── Cache check ────────────────────────────────────────────────
|
||||||
var cacheKey = showBranding ? $"{isin}:branded" : isin;
|
var baseCacheKey = showBranding ? $"{isin}:branded" : isin;
|
||||||
var cached = _cache.Get(cacheKey);
|
var expiredCacheKey = showBranding ? $"{isin}:expired:branded" : $"{isin}:expired";
|
||||||
|
|
||||||
|
var cached = _cache.Get(baseCacheKey) ?? _cache.Get(expiredCacheKey);
|
||||||
if (cached != null)
|
if (cached != null)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Report per ISIN {Isin} servito da cache ({Size} bytes)", isin, cached.Length);
|
_logger.LogInformation("Report per ISIN {Isin} servito da cache ({Size} bytes)", isin, cached.Length);
|
||||||
@@ -60,40 +65,56 @@ public class ReportOrchestrator : IReportOrchestrator
|
|||||||
ShowBranding = showBranding,
|
ShowBranding = showBranding,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Determina se lo scenario ha dati validi (evita doppia chiamata SP)
|
// ── 2. Determina il tipo di report ────────────────────────────
|
||||||
bool isScenarioAllowed = reportData.Scenario.Rows.Count > 0;
|
bool isExpired = !string.IsNullOrEmpty(reportData.Info.Stato)
|
||||||
|
&& reportData.Info.Stato != "Quotazione";
|
||||||
|
|
||||||
|
var cacheKey = isExpired ? expiredCacheKey : baseCacheKey;
|
||||||
|
|
||||||
_logger.LogInformation(
|
_logger.LogInformation(
|
||||||
"Dati recuperati per {Isin}: {SottostantiCount} sottostanti, {EventiCount} eventi, Scenario: {ScenarioAllowed}",
|
"Dati recuperati per {Isin}: Stato={Stato}, isExpired={IsExpired}, {EventiCount} eventi",
|
||||||
isin, reportData.Info.Sottostanti.Count, reportData.Eventi.Count, isScenarioAllowed);
|
isin, reportData.Info.Stato, isExpired, reportData.Eventi.Count);
|
||||||
|
|
||||||
// ── 2. Genera le sezioni PDF ───────────────────────────────────
|
// ── 3. Genera le sezioni PDF ──────────────────────────────────
|
||||||
var pdfSections = new List<PdfDocument>();
|
var pdfSections = new List<PdfDocument>();
|
||||||
|
|
||||||
|
if (isExpired)
|
||||||
|
{
|
||||||
|
// Flusso expired: ExpiredAnagrafica + Eventi + Chart
|
||||||
|
pdfSections.Add(_expiredAnagraficaRenderer.Render(reportData));
|
||||||
|
_logger.LogInformation("Sezione 'ExpiredAnagrafica' generata per {Isin}", isin);
|
||||||
|
|
||||||
|
var eventiRenderer = _sectionRenderers.First(r => r.SectionName == "Eventi");
|
||||||
|
pdfSections.Add(eventiRenderer.Render(reportData));
|
||||||
|
_logger.LogInformation("Sezione 'Eventi' generata per {Isin}", isin);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Flusso attuale: Anagrafica + Eventi + Scenario (condizionale)
|
||||||
|
bool isScenarioAllowed = reportData.Scenario.Rows.Count > 0;
|
||||||
|
|
||||||
foreach (var renderer in _sectionRenderers.OrderBy(r => r.Order))
|
foreach (var renderer in _sectionRenderers.OrderBy(r => r.Order))
|
||||||
{
|
{
|
||||||
// Salta la sezione scenario se il certificato è Protection
|
|
||||||
if (renderer.SectionName == "Scenario" && !isScenarioAllowed)
|
if (renderer.SectionName == "Scenario" && !isScenarioAllowed)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Sezione Scenario saltata per {Isin} (certificato Protection)", isin);
|
_logger.LogInformation("Sezione Scenario saltata per {Isin}", isin);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var sectionPdf = renderer.Render(reportData);
|
pdfSections.Add(renderer.Render(reportData));
|
||||||
pdfSections.Add(sectionPdf);
|
|
||||||
_logger.LogInformation("Sezione '{Section}' generata per {Isin}", renderer.SectionName, isin);
|
_logger.LogInformation("Sezione '{Section}' generata per {Isin}", renderer.SectionName, isin);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Errore nella generazione della sezione '{Section}' per {Isin}",
|
_logger.LogError(ex, "Errore nella sezione '{Section}' per {Isin}", renderer.SectionName, isin);
|
||||||
renderer.SectionName, isin);
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ── 3. Genera/recupera il grafico ──────────────────────────────
|
// ── 4. Grafico (entrambi i flussi) ────────────────────────────
|
||||||
var chartPdf = await _chartRenderer.RenderAsync(isin);
|
var chartPdf = await _chartRenderer.RenderAsync(isin);
|
||||||
if (chartPdf != null)
|
if (chartPdf != null)
|
||||||
{
|
{
|
||||||
@@ -101,20 +122,16 @@ public class ReportOrchestrator : IReportOrchestrator
|
|||||||
_logger.LogInformation("Sezione Grafico aggiunta per {Isin}", isin);
|
_logger.LogInformation("Sezione Grafico aggiunta per {Isin}", isin);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── 4. Unisci tutto ────────────────────────────────────────────
|
// ── 5. Unisci tutto ────────────────────────────────────────────
|
||||||
var finalPdf = _merger.Merge(pdfSections);
|
var finalPdf = _merger.Merge(pdfSections);
|
||||||
|
|
||||||
_logger.LogInformation("Report generato per {Isin}: {Size} bytes, {Sections} sezioni",
|
_logger.LogInformation("Report generato per {Isin}: {Size} bytes, {Sections} sezioni",
|
||||||
isin, finalPdf.Length, pdfSections.Count);
|
isin, finalPdf.Length, pdfSections.Count);
|
||||||
|
|
||||||
// Salva in cache
|
|
||||||
_cache.Set(cacheKey, finalPdf);
|
_cache.Set(cacheKey, finalPdf);
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
foreach (var doc in pdfSections)
|
foreach (var doc in pdfSections)
|
||||||
{
|
|
||||||
doc.Close(true);
|
doc.Close(true);
|
||||||
}
|
|
||||||
|
|
||||||
return finalPdf;
|
return finalPdf;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user