Files
SmartReports/docs/superpowers/specs/2026-06-08-fund-report-design.md
2026-06-08 17:10:47 +02:00

244 lines
9.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Design Spec — Report ETF/Fondi
**Data:** 2026-06-08
**Scope:** Nuovo report PDF a 2 pagine per ETF/fondi, con endpoint dedicati `/api/report/fund/` e `/api/chart/fund/`. Indipendente dal flusso certificati.
---
## 1. Endpoints
### Report PDF
| Metodo | Route | Comportamento |
|--------|-------|---------------|
| GET | `/api/report/fund/by-isin/{isin}` | PDF inline |
| GET | `/api/report/fund?p={isin_cifrato}` | PDF inline (ISIN cifrato, stesso CryptoHelper) |
| GET | `/api/report/fund?alias={id}` | PDF inline (alias → ISIN via `FindIsinByAliasIdAsync`) |
| GET | `/api/report/fund/download?p={...}` | PDF come allegato (`Content-Disposition: attachment`) |
### Grafico standalone
| Metodo | Route | Comportamento |
|--------|-------|---------------|
| GET | `/api/chart/fund/{isin}` | PNG/PDF inline (vedi §4) |
### Parametri opzionali (tutti gli endpoint report)
| Parametro | Default | Effetto |
|-----------|---------|---------|
| `?branding=true` | `false` | Footer "Powered by [Smart Roots](https://www.smart-roots.net)" — riusa `PdfTheme.DrawFooter` già esistente |
### Parametri opzionali (endpoint chart)
| Parametro | Default | Effetto |
|-----------|---------|---------|
| `?format=png\|pdf\|jpg\|jpeg` | `png` | Formato output |
| `?save=true` | `false` | Salva JPEG su disco (`ChartSettings:SavePath`) |
---
## 2. Architettura
```
HTTP → FundReportController
├── FundDataService sfih_GetOptDettagli @ISIN → FundInfo
├── FundReportOrchestrator
│ ├── FundAnagraficaRenderer → PdfDocument (Pagina 1)
│ ├── FundChartRenderer → PdfDocument (Pagina 2, placeholder)
│ └── PdfMergerService → byte[] (riusato)
└── PdfCacheService → cache chiave "fund:{isin}[:branded]"
HTTP → FundChartController
├── FundChartDataService SP da definire → FundChartData
└── FundSkiaChartRenderer → PNG/JPEG/PDF
```
**Riuso componenti esistenti:** `PdfMergerService`, `PdfCacheService`, `PdfTheme` (incluso `DrawFooter`), `CryptoHelper`.
**Nessuna modifica** ai controller/renderer/service certificati esistenti.
---
## 3. Pagina 1 — Anagrafica (Layout C)
### Struttura visiva
```
┌─────────────────────────────────────────────────────────┐
│ [BLUE BAR] {typ} — {str} — {isn} │
├──────────────────────────────────────────────────────────┤
│ [RANK strip] rnk │ [PREZZO strip] prz val │ dpz │
├──────────────────────────────────────────────────────────┤
│ Dati Anagrafici │ ESG Score │ Perf·Vol·R/R grid │
│ (flex 1.3) │ (flex 0.9) │ (flex 1.4) │
└──────────────────────────────────────────────────────────┘
│ footer: [Powered by Smart Roots]? pagina N │
```
### Mapping campi SP → sezioni
**Titolo:**
- `{typ} — {str} — {isn}` (es. `ETF — WisdomTree … — IE00BDVPNG13`)
**Strip Rank/Prezzo:**
- Rank: `rnk`
- Prezzo: `prz` + `val`
- Data aggiornamento: `dpz` (formato `dd/MM/yyyy`)
**Dati Anagrafici** (tabella label/valore):
| Label | Campo SP |
|-------|----------|
| Società | `soc` |
| Categoria MS | `msc` |
| Tipo | `typ` |
| Valuta | `val` |
| Hedged | `hed` (→ `"sì"` / `"no"`) |
| Benchmark | `bmk` |
| Spese correnti | `spc` (→ formato `0.##%`) |
| Catalogo | `itr` |
| Proventi | `prv` |
| Data lancio | `daf` (formato `dd/MM/yyyy`) |
| Patrimonio | `pat` (formato `#,##0 EUR`) |
**ESG Score** (4 card verdi verticali):
- Sustainability: `sus`
- Environmental: `env`
- Social: `ssc`
- Governance: `gov`
- Se un singolo valore è `0` (AMC/fallback), viene mostrato come `"—"`. La sezione ESG è sempre visibile.
**Griglia Performance/Volatilità/RendRisk** (3×2):
| Periodo | Perf | Vol | R/R |
|---------|------|-----|-----|
| 3 Mesi | `p3M` | `v3M` | `r3M` |
| 6 Mesi | `p6M` | `v6M` | `r6M` |
| Da inizio anno | `pYD` | `vYD` | `rYD` |
| 1 Anno | `p1Y` | `v1Y` | `r1Y` |
| 3 Anni | `p3Y` | `v3Y` | `r3Y` |
| 5 Anni | `p5Y` | `v5Y` | `r5Y` |
Colori: Perf positiva → `PositiveGreenBrush`, negativa → `NegativeRedBrush`, Vol e R/R → testo normale.
---
## 4. Pagina 2 — Grafico (placeholder)
Il rendering della pagina 2 è un **placeholder** in questa fase. La SP del grafico verrà fornita in seguito.
`FundChartRenderer` restituisce per ora una pagina con il testo "Grafico non disponibile" oppure viene omessa se la SP non è configurata. La struttura è pronta per accogliere la SP senza modifiche all'orchestratore.
`FundSkiaChartRenderer` (endpoint `/api/chart/fund/{isin}`):
- Singola linea: close price storico (`Px_Close` da SP da definire)
- Supporta `?format=png|jpg|jpeg|pdf` e `?save=true`
- Nessuna logica WorstOf/barriere/label complesse
---
## 5. Modelli
**File:** `Models/FundModels.cs`
```csharp
// Mapping 1:1 con result set di sfih_GetOptDettagli
public class FundInfo
{
public string Isin { get; set; } // isn
public string Strumento { get; set; } // str
public string Tipo { get; set; } // typ
public string Societa { get; set; } // soc
public string CategoriaMorningstar { get; set; } // msc
public string Valuta { get; set; } // val
public string Hedged { get; set; } // hed
public string Benchmark { get; set; } // bmk
public string Catalogo { get; set; } // itr
public string Proventi { get; set; } // prv
public DateTime? DataLancio { get; set; } // daf
public decimal? Patrimonio { get; set; } // pat
public decimal? SpeseCorrenti { get; set; } // spc
public decimal? Prezzo { get; set; } // prz
public DateTime? DataPrezzo { get; set; } // dpz
public decimal? Rank { get; set; } // rnk
// Performance
public decimal? P3M { get; set; } public decimal? P6M { get; set; }
public decimal? PYD { get; set; } public decimal? P1Y { get; set; }
public decimal? P3Y { get; set; } public decimal? P5Y { get; set; }
// Volatilità
public decimal? V3M { get; set; } public decimal? V6M { get; set; }
public decimal? VYD { get; set; } public decimal? V1Y { get; set; }
public decimal? V3Y { get; set; } public decimal? V5Y { get; set; }
// RendRisk
public decimal? R3M { get; set; } public decimal? R6M { get; set; }
public decimal? RYD { get; set; } public decimal? R1Y { get; set; }
public decimal? R3Y { get; set; } public decimal? R5Y { get; set; }
// ESG
public decimal? Sustainability { get; set; } // sus
public decimal? Environmental { get; set; } // env
public decimal? Social { get; set; } // ssc
public decimal? Governance { get; set; } // gov
}
public class FundReportData
{
public FundInfo Info { get; set; }
public bool ShowBranding { get; set; }
}
```
---
## 6. Interfacce
```csharp
// IFundDataService
Task<FundInfo?> GetFundInfoAsync(string isin);
Task<string?> FindIsinByAliasIdAsync(string aliasId); // riusa stessa logica
// IFundReportOrchestrator
Task<byte[]> GenerateReportAsync(string isin, bool showBranding = false);
```
---
## 7. Registrazioni Program.cs
```csharp
builder.Services.AddScoped<IFundDataService, FundDataService>();
builder.Services.AddScoped<IFundReportOrchestrator, FundReportOrchestrator>();
builder.Services.AddScoped<FundAnagraficaRenderer>();
builder.Services.AddScoped<FundChartRenderer>(); // placeholder
builder.Services.AddScoped<FundSkiaChartRenderer>(); // per /api/chart/fund/
```
---
## 8. Cache
Chiave pattern: `fund:{isin}` + suffisso `:branded` se `showBranding=true`.
Riusa il `PdfCacheService` esistente (stesso TTL da `appsettings.json`).
---
## 9. File da creare
| File | Descrizione |
|------|-------------|
| `Models/FundModels.cs` | `FundInfo`, `FundReportData`, `FundChartData` (placeholder) |
| `Services/Interfaces/IFundServices.cs` | `IFundDataService`, `IFundReportOrchestrator` |
| `Services/Implementations/FundDataService.cs` | Chiama `sfih_GetOptDettagli` |
| `Services/Implementations/FundAnagraficaRenderer.cs` | Pagina 1 layout C |
| `Services/Implementations/FundChartRenderer.cs` | Pagina 2 placeholder |
| `Services/Implementations/FundReportOrchestrator.cs` | Coordina anagrafica + chart + merge + cache |
| `Services/Implementations/FundSkiaChartRenderer.cs` | Rendering grafico (placeholder, SP da aggiungere) |
| `Controllers/FundReportController.cs` | 4 endpoint `/api/report/fund/` |
| `Controllers/FundChartController.cs` | 1 endpoint `/api/chart/fund/` |
---
## 10. Fuori scope (questa iterazione)
- SP grafico: `FundChartDataService` e `FundSkiaChartRenderer` rimangono placeholder fino alla fornitura della SP
- Parametri `?natixis`, `?dividend` — non applicabili ai fondi
- Test automatici (nessun test nel progetto al momento)