docs: add dividend section design spec
This commit is contained in:
148
docs/superpowers/specs/2026-03-23-dividend-section-design.md
Normal file
148
docs/superpowers/specs/2026-03-23-dividend-section-design.md
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
# Dividend Section — Design Spec
|
||||||
|
**Data:** 2026-03-23
|
||||||
|
**Progetto:** SmartReports / CertReports.Syncfusion
|
||||||
|
**Stato:** Approvato
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Obiettivo
|
||||||
|
|
||||||
|
Aggiungere il supporto ai dati dividendi dei sottostanti nel report PDF, attivabile tramite il parametro query `?dividend=true`. Quando attivo, i dati dividendi (già presenti nella SP `rpt_Details_UL_ISIN`) vengono visualizzati in una pagina landscape dedicata con tabella unificata Sottostanti+Dividendi a header raggruppati.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Parametro API
|
||||||
|
|
||||||
|
```
|
||||||
|
?dividend=true → attiva la pagina dividendi
|
||||||
|
?dividend=false → comportamento invariato (default)
|
||||||
|
```
|
||||||
|
|
||||||
|
Disponibile su tutti gli endpoint report esistenti (`/by-isin/{isin}`, `?p=`, `?alias=`, `/download`).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Comportamento
|
||||||
|
|
||||||
|
### Con `dividend=false` (default)
|
||||||
|
Il report è identico a quello attuale. Nessuna modifica visibile.
|
||||||
|
|
||||||
|
### Con `dividend=true`
|
||||||
|
1. La tabella Sottostanti **non viene renderizzata** in Sezione 1 (né in `AnagraficaSectionRenderer` né in `ExpiredAnagraficaSectionRenderer`).
|
||||||
|
2. Dopo la Sezione 1 (Anagrafica) e prima della Sezione 2 (Eventi) viene inserita una **pagina landscape dedicata** con la tabella unificata Sottostanti+Dividendi.
|
||||||
|
3. Il resto del report (Eventi, Scenario, Grafico) rimane invariato.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Struttura tabella landscape
|
||||||
|
|
||||||
|
Pagina A4 orizzontale (landscape), margini standard (`PdfTheme.PageMargin`).
|
||||||
|
Larghezza utile: ~770pt. Font: `PdfTheme.TableFont` (7pt).
|
||||||
|
|
||||||
|
### Header a 2 livelli (colspan)
|
||||||
|
|
||||||
|
| Riga 1 | Nome | SOTTOSTANTE (×3) | BARRIERE (×5) | DIVIDENDI (×6) |
|
||||||
|
|--------|------|------------------|---------------|----------------|
|
||||||
|
| Riga 2 | — | Strike, Last, % Perf. | Barr.Cap., Buf.Cap., Trig.CPN, Buf.CPN, Trig.AC | Data Stacco, Data Pag., Importo, Rend., Imp.Fut., Rend.Fut. |
|
||||||
|
|
||||||
|
- Gruppo **SOTTOSTANTE** + **BARRIERE**: sfondo `#1565C0` (AccentBlue)
|
||||||
|
- Gruppo **DIVIDENDI**: sfondo `#0A3880` (blu scuro) per differenziazione visiva
|
||||||
|
- Separatore verticale blu (`#64B5F6`) tra colonna T.AC e colonna Data Stacco
|
||||||
|
- Colori performance: negativi `NegativeRed`, positivi `PositiveGreen`
|
||||||
|
- Righe alternate: `TableAltRow`
|
||||||
|
|
||||||
|
### Larghezze colonne indicative (totale ~770pt)
|
||||||
|
|
||||||
|
| Colonna | Width (pt) |
|
||||||
|
|---------|-----------|
|
||||||
|
| Nome | 90 |
|
||||||
|
| Strike | 50 |
|
||||||
|
| Last | 50 |
|
||||||
|
| % Perf. | 46 |
|
||||||
|
| Barr.Cap. | 50 |
|
||||||
|
| Buf.Cap. | 46 |
|
||||||
|
| Trig.CPN | 50 |
|
||||||
|
| Buf.CPN | 46 |
|
||||||
|
| Trig.AC | 46 |
|
||||||
|
| Data Stacco | 54 |
|
||||||
|
| Data Pag. | 54 |
|
||||||
|
| Importo | 40 |
|
||||||
|
| Rend. | 40 |
|
||||||
|
| Imp.Fut. | 40 |
|
||||||
|
| Rend.Fut. | 40 |
|
||||||
|
| **Totale** | **742** |
|
||||||
|
|
||||||
|
Le larghezze vengono scalate proporzionalmente a `w / total` per adattarsi alla larghezza utile esatta.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Mapping dati
|
||||||
|
|
||||||
|
I campi dividendi sono già nel modello `Sottostante` (da SP `rpt_Details_UL_ISIN`):
|
||||||
|
|
||||||
|
| Colonna PDF | Campo modello |
|
||||||
|
|-------------|--------------|
|
||||||
|
| Data Stacco | `DividendExDate` |
|
||||||
|
| Data Pag. | `DividendPayDate` |
|
||||||
|
| Importo | `DividendAmount` |
|
||||||
|
| Rend. | `DividendYield` |
|
||||||
|
| Imp.Fut. | `DividendFutAmount` |
|
||||||
|
| Rend.Fut. | `DividendFutYield` |
|
||||||
|
|
||||||
|
Nessuna modifica al data service o alle stored procedure.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Componenti da modificare / creare
|
||||||
|
|
||||||
|
### 1. `CertificateReportData` (Models/CertificateModels.cs)
|
||||||
|
Aggiungere proprietà:
|
||||||
|
```csharp
|
||||||
|
public bool ShowDividend { get; set; } = false;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. `ReportController` (Controllers/ReportController.cs)
|
||||||
|
Leggere il parametro `dividend` da query string e impostare `data.ShowDividend`.
|
||||||
|
|
||||||
|
### 3. `PdfCacheService`
|
||||||
|
La chiave cache deve includere il flag dividend per evitare collisioni:
|
||||||
|
- `{isin}` — no branding, no dividend
|
||||||
|
- `{isin}:branded` — branding, no dividend
|
||||||
|
- `{isin}:dividend` — no branding, dividend
|
||||||
|
- `{isin}:branded:dividend` — branding + dividend
|
||||||
|
|
||||||
|
### 4. `AnagraficaSectionRenderer`
|
||||||
|
Condizione nel metodo `Render()`: se `data.ShowDividend == true`, saltare il blocco "SEZIONE C: SOTTOSTANTI".
|
||||||
|
|
||||||
|
### 5. `ExpiredAnagraficaSectionRenderer`
|
||||||
|
Stessa condizione: se `data.ShowDividend == true`, saltare il blocco "SEZIONE C: SOTTOSTANTI".
|
||||||
|
|
||||||
|
### 6. `DividendSectionRenderer` (nuovo file)
|
||||||
|
- Classe: `DividendSectionRenderer`
|
||||||
|
- **Non** implementa `IPdfSectionRenderer` (non partecipa al ciclo ordinato)
|
||||||
|
- Registrazione: `AddScoped<DividendSectionRenderer>()` in `Program.cs`
|
||||||
|
- Metodo: `PdfDocument Render(CertificateReportData data)`
|
||||||
|
- Pagina landscape A4, titolo "Sottostanti e Dividendi", tabella con header a 2 livelli
|
||||||
|
- Footer: `PdfTheme.DrawFooter(g, w, h, 1, data.ShowBranding)`
|
||||||
|
|
||||||
|
### 7. `ReportOrchestrator`
|
||||||
|
- Iniettare `DividendSectionRenderer` nel costruttore
|
||||||
|
- In entrambi i flussi (attivo ed expired): se `data.ShowDividend == true`, chiamare `DividendSectionRenderer.Render(data)` e aggiungerlo alla lista documenti da mergiare, subito dopo la Sezione 1 (Anagrafica)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Note implementative
|
||||||
|
|
||||||
|
- **Header colspan su PdfGrid**: Syncfusion `PdfGrid` non supporta nativamente colspan negli header. Implementare i due livelli di header come righe manuali disegnate con `DrawRectangle` + `DrawString`, poi la griglia dati sotto. Questa è la stessa tecnica usata per altri header complessi nel progetto.
|
||||||
|
- **Colori negativi/positivi**: applicare `ColorPerformanceCell` su % Perf., Buf.Cap., Buf.CPN, Rend., Rend.Fut. — stessa logica di `AnagraficaSectionRenderer`.
|
||||||
|
- **Valori assenti**: celle dividendo vuote mostrano `"—"`.
|
||||||
|
- Il parametro `dividend` è indipendente da `branding` — entrambi possono essere attivi contemporaneamente.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Non in scope
|
||||||
|
|
||||||
|
- Modifiche alle stored procedure o al data service
|
||||||
|
- Nuove colonne nel modello `Sottostante`
|
||||||
|
- Modifiche al grafico o agli eventi
|
||||||
|
- Paginazione automatica della tabella dividendi (assumiamo max ~20 sottostanti per certificato)
|
||||||
Reference in New Issue
Block a user