From cdbdfeede17d892576f106a7fd9af68b631e7d13 Mon Sep 17 00:00:00 2001 From: SmartRootsSrl Date: Sat, 21 Mar 2026 10:21:20 +0100 Subject: [PATCH] docs: update expired report spec after review (cache keys, orchestrator logic, chart signature) --- ...03-21-expired-certificate-report-design.md | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/docs/superpowers/specs/2026-03-21-expired-certificate-report-design.md b/docs/superpowers/specs/2026-03-21-expired-certificate-report-design.md index c4fc315..fde072a 100644 --- a/docs/superpowers/specs/2026-03-21-expired-certificate-report-design.md +++ b/docs/superpowers/specs/2026-03-21-expired-certificate-report-design.md @@ -16,7 +16,7 @@ Implementare un secondo template di report PDF per certificati non più in quota | Pagina | Renderer | Contenuto | |--------|----------|-----------| -| 1 | `ExpiredAnagraficaSectionRenderer` | Titolo + Caratteristiche + Analisi | +| 1 | `ExpiredAnagraficaSectionRenderer` (nuovo) | Titolo + Caratteristiche + Analisi | | 2 | `EventiSectionRenderer` (riusato) | Lista eventi (identica all'attuale) | | 3 | `ChartSectionRenderer` (riusato) | Grafico performance (identico all'attuale) | @@ -98,37 +98,42 @@ Nessuna altra modifica alle query o agli altri servizi dati. Dopo il caricamento dei dati (`CertificateDataService`), leggere `data.Info.Stato` per scegliere il flusso: -```csharp -bool isExpired = data.Info.Stato != "Quotazione" && !string.IsNullOrEmpty(data.Info.Stato); +**Strategia isExpired — denylist:** il check usa `!= "Quotazione"` (denylist), così qualsiasi nuovo stato non previsto viene trattato come expired piuttosto che come attivo. Se in futuro si aggiungono stati con report differenti, si sostituirà con un allowlist esplicito. + +```csharp +bool isExpired = !string.IsNullOrEmpty(data.Info.Stato) && data.Info.Stato != "Quotazione"; +// Copre: "Revocato", "Scaduto", "Rimborsato" — e qualsiasi stato futuro non-attivo -List sections; if (isExpired) { // Flusso expired: ExpiredAnagrafica + Eventi + Chart - sections = new List - { - _expiredAnagraficaRenderer.Render(data), - eventiRenderer.Render(data), - // chart (async, può essere null) - }; + var eventiRenderer = _sectionRenderers.First(r => r.SectionName == "Eventi"); + pdfSections.Add(_expiredAnagraficaRenderer.Render(data)); + pdfSections.Add(eventiRenderer.Render(data)); + // Chart: await _chartRenderer.RenderAsync(data.Info.Isin) — aggiunto se non null } else { - // Flusso attuale: Anagrafica + Eventi + Scenario (condizionale) + Chart - // logica esistente invariata + // Flusso attuale: foreach _sectionRenderers.OrderBy(r => r.Order) — logica esistente invariata } ``` +**Come si ottiene EventiSectionRenderer nel flusso expired:** tramite `_sectionRenderers.First(r => r.SectionName == "Eventi")`. È già registrato come `IPdfSectionRenderer` e presente nella collection iniettata. + +**Firma ChartRenderer:** `await _chartRenderer.RenderAsync(data.Info.Isin)` — stessa chiamata del flusso attivo, restituisce `PdfDocument?` (null se il grafico non è disponibile). + Il renderer `ExpiredAnagraficaSectionRenderer` è iniettato direttamente nell'orchestratore (non via `IEnumerable`) per evitare che venga incluso nel ciclo del flusso normale. ### Cache — chiavi separate -| Scenario | Chiave cache | -|----------|-------------| -| Attivo, no branding | `{isin}` | -| Attivo, branding | `{isin}:branded` | -| Expired, no branding | `{isin}:expired` | -| Expired, branding | `{isin}:expired:branded` | +Le chiavi sono passate a `_cache.Get/Set` a livello orchestratore; `PdfCacheService.CacheKey()` aggiunge poi il prefisso `report_pdf_` internamente (comportamento invariato per entrambi i flussi). + +| Scenario | Chiave passata all'orchestratore | Chiave effettiva in memoria | +|----------|----------------------------------|-----------------------------| +| Attivo, no branding | `{isin}` | `report_pdf_{isin}` | +| Attivo, branding | `{isin}:branded` | `report_pdf_{isin}:branded` | +| Expired, no branding | `{isin}:expired` | `report_pdf_{isin}:expired` | +| Expired, branding | `{isin}:expired:branded` | `report_pdf_{isin}:expired:branded` | ---