diff --git a/docs/superpowers/specs/2026-03-24-eventi-righe-non-raggiungibili-design.md b/docs/superpowers/specs/2026-03-24-eventi-righe-non-raggiungibili-design.md new file mode 100644 index 0000000..3271a1e --- /dev/null +++ b/docs/superpowers/specs/2026-03-24-eventi-righe-non-raggiungibili-design.md @@ -0,0 +1,94 @@ +# Design: Righe non raggiungibili in Lista Eventi + +**Data:** 2026-03-24 +**Scope:** Solo certificati non in quotazione (Stato ≠ "Quotazione") +**Feature:** Evidenziare con testo grigio dimmed le righe della Lista Eventi con Data Osservazione > Data Rimborso + +--- + +## Contesto + +Nei report per certificati non in quotazione (Scaduto/Rimborsato/Revocato), la tabella Lista + Eventi può contenere righe con date di osservazione successive alla data di rimborso effettivo. Questi eventi non sono mai stati raggiungibili perché il certificato ha rimborsato anticipatamente. È utile evidenziarli visivamente per distinguerli dagli eventi effettivamente avvenuti. + +## Requisito + +Per i soli certificati non in quotazione (`isExpired = true`): +- Le righe della Lista Eventi dove `ObservationDate > DataRimborso` devono essere visualizzate con **testo grigio dimmed** (`#AAAAAA`) +- Il colore di sfondo alternato (bianco / azzurro chiaro) rimane invariato +- Tutto il testo della riga viene dimmed, inclusa la colonna Pagato (nessuna eccezione per il verde "SI") + +## Design approvato: Opzione A + +Testo grigio dimmed su sfondo invariato. Pattern zebra della tabella non viene alterato. + +--- + +## Modifiche + +### 1. `CertReports.Syncfusion/Helpers/PdfTheme.cs` + +Aggiungere due costanti statiche: + +```csharp +public static readonly PdfColor GrayedOut = Color.FromArgb(255, 170, 170, 170); +public static readonly PdfBrush GrayedOutBrush = new PdfSolidBrush(GrayedOut); +``` + +### 2. `CertReports.Syncfusion/Services/Implementations/EventiSectionRenderer.cs` + +Nel metodo `Render()`, nel branch `isExpired`, aggiungere: + +**Prima del loop righe** — parse una volta `DataRimborso`: + +```csharp +DateTime? rimborsoDate = null; +if (!string.IsNullOrEmpty(data.Info.DataRimborso)) + DateTime.TryParseExact(data.Info.DataRimborso, "dd/MM/yyyy", + CultureInfo.InvariantCulture, DateTimeStyles.None, out var d) + .Let(_ => rimborsoDate = d); // o: if (parsed) rimborsoDate = d; +``` + +**Nel loop righe, dopo assegnazione celle** — determinare se la riga è non raggiungibile e applicare il brush: + +```csharp +bool isUnreachable = false; +if (isExpired && rimborsoDate.HasValue && + DateTime.TryParseExact(evt.ObservationDate, "dd/MM/yyyy", + CultureInfo.InvariantCulture, DateTimeStyles.None, out var obsDate)) +{ + isUnreachable = obsDate > rimborsoDate.Value; +} + +if (isUnreachable) + foreach (var cell in row.Cells.OfType()) + cell.Style.TextBrush = PdfTheme.GrayedOutBrush as PdfBrush; +``` + +Questo blocco va applicato **dopo** la logica delle righe alternate e **dopo** l'evidenziazione verde di Pagato = "SI", sovrascrivendo entrambi sul TextBrush. + +--- + +## Edge Cases + +| Caso | Comportamento | +|------|--------------| +| `DataRimborso` vuota o non parseable | Nessuna riga viene dimmed (skip sicuro) | +| `ObservationDate` non parseable | Quella riga non viene dimmed (skip per sicurezza) | +| Certificato in quotazione (`!isExpired`) | Logica completamente ignorata | +| `ObservationDate == DataRimborso` | Non dimmed (la data uguale è ancora raggiungibile) | + +--- + +## File non modificati + +- `CertificateModels.cs` — nessun flag aggiuntivo nel modello +- Stored procedure — nessuna modifica DB +- `ExpiredAnagraficaSectionRenderer.cs`, `ChartSectionRenderer.cs` — non coinvolti + +--- + +## Dipendenze + +- `System.Globalization` già disponibile nel progetto +- Nessuna nuova dipendenza NuGet