docs: update expired report spec after review (cache keys, orchestrator logic, chart signature)
This commit is contained in:
@@ -16,7 +16,7 @@ Implementare un secondo template di report PDF per certificati non più in quota
|
|||||||
|
|
||||||
| Pagina | Renderer | Contenuto |
|
| Pagina | Renderer | Contenuto |
|
||||||
|--------|----------|-----------|
|
|--------|----------|-----------|
|
||||||
| 1 | `ExpiredAnagraficaSectionRenderer` | Titolo + Caratteristiche + Analisi |
|
| 1 | `ExpiredAnagraficaSectionRenderer` (nuovo) | Titolo + Caratteristiche + Analisi |
|
||||||
| 2 | `EventiSectionRenderer` (riusato) | Lista eventi (identica all'attuale) |
|
| 2 | `EventiSectionRenderer` (riusato) | Lista eventi (identica all'attuale) |
|
||||||
| 3 | `ChartSectionRenderer` (riusato) | Grafico performance (identico 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:
|
Dopo il caricamento dei dati (`CertificateDataService`), leggere `data.Info.Stato` per scegliere il flusso:
|
||||||
|
|
||||||
```csharp
|
**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.
|
||||||
bool isExpired = data.Info.Stato != "Quotazione" && !string.IsNullOrEmpty(data.Info.Stato);
|
|
||||||
|
```csharp
|
||||||
|
bool isExpired = !string.IsNullOrEmpty(data.Info.Stato) && data.Info.Stato != "Quotazione";
|
||||||
|
// Copre: "Revocato", "Scaduto", "Rimborsato" — e qualsiasi stato futuro non-attivo
|
||||||
|
|
||||||
List<PdfDocument> sections;
|
|
||||||
if (isExpired)
|
if (isExpired)
|
||||||
{
|
{
|
||||||
// Flusso expired: ExpiredAnagrafica + Eventi + Chart
|
// Flusso expired: ExpiredAnagrafica + Eventi + Chart
|
||||||
sections = new List<PdfDocument>
|
var eventiRenderer = _sectionRenderers.First(r => r.SectionName == "Eventi");
|
||||||
{
|
pdfSections.Add(_expiredAnagraficaRenderer.Render(data));
|
||||||
_expiredAnagraficaRenderer.Render(data),
|
pdfSections.Add(eventiRenderer.Render(data));
|
||||||
eventiRenderer.Render(data),
|
// Chart: await _chartRenderer.RenderAsync(data.Info.Isin) — aggiunto se non null
|
||||||
// chart (async, può essere null)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Flusso attuale: Anagrafica + Eventi + Scenario (condizionale) + Chart
|
// Flusso attuale: foreach _sectionRenderers.OrderBy(r => r.Order) — logica esistente invariata
|
||||||
// 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<IPdfSectionRenderer>`) per evitare che venga incluso nel ciclo del flusso normale.
|
Il renderer `ExpiredAnagraficaSectionRenderer` è iniettato direttamente nell'orchestratore (non via `IEnumerable<IPdfSectionRenderer>`) per evitare che venga incluso nel ciclo del flusso normale.
|
||||||
|
|
||||||
### Cache — chiavi separate
|
### Cache — chiavi separate
|
||||||
|
|
||||||
| Scenario | Chiave cache |
|
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).
|
||||||
|----------|-------------|
|
|
||||||
| Attivo, no branding | `{isin}` |
|
| Scenario | Chiave passata all'orchestratore | Chiave effettiva in memoria |
|
||||||
| Attivo, branding | `{isin}:branded` |
|
|----------|----------------------------------|-----------------------------|
|
||||||
| Expired, no branding | `{isin}:expired` |
|
| Attivo, no branding | `{isin}` | `report_pdf_{isin}` |
|
||||||
| Expired, branding | `{isin}:expired:branded` |
|
| 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` |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user