223 lines
10 KiB
Markdown
223 lines
10 KiB
Markdown
# SmartReports
|
|
|
|
Generatore di report PDF per certificati finanziari strutturati, sviluppato in ASP.NET Core 8 con libreria Syncfusion PDF (Community License) e SkiaSharp per i grafici.
|
|
|
|
## Caratteristiche principali
|
|
|
|
- Generazione PDF multi-sezione da dati SQL Server
|
|
- **Due template report certificati**: in quotazione (4 sezioni) e non in quotazione / scaduti / rimborsati / revocati (3 sezioni) — rilevamento automatico dal campo `Stato`
|
|
- **Report ETF/Fondi**: 2 pagine — anagrafica con layout a 3 colonne (Dati Anagrafici, ESG Score, griglia Performance/Volatilità/RendRisk) + grafico storico prezzi
|
|
- **Pagina dividendi opzionale** (`?dividend=true`): pagina landscape con tabella Sottostanti+Dividendi a header raggruppati
|
|
- Grafico performance sottostanti (SkiaSharp → PNG in memoria)
|
|
- Footer con branding opzionale e hyperlink cliccabile
|
|
- Cache in memoria per ISIN già generati (chiavi separate per ogni combinazione di flag)
|
|
- Endpoint per PDF inline, download, grafico standalone v1, grafico V2 multi-formato e **grafico fondi**
|
|
- Supporto Docker
|
|
|
|
## Stack tecnologico
|
|
|
|
| Componente | Tecnologia |
|
|
|-----------|-----------|
|
|
| Framework | ASP.NET Core 8 |
|
|
| PDF | Syncfusion PDF v33 (Community License) |
|
|
| Grafici | SkiaSharp |
|
|
| Database | SQL Server (Microsoft.Data.SqlClient v5) |
|
|
| Runtime | .NET 8 |
|
|
|
|
## Struttura del report
|
|
|
|
### Certificati in quotazione (Stato = "Quotazione") — 4 sezioni (+1 opzionale)
|
|
|
|
| Sezione | Contenuto |
|
|
|---------|-----------|
|
|
| **1 — Anagrafica** | Header con Tipologia / Data / Bid / Ask, caratteristiche prodotto, analisi KV (inclusi Direzione, RendimentoPotenziale, CategoryID), tabella sottostanti (omessa se `?dividend=true`) |
|
|
| **1b — Sottostanti e Dividendi** *(opzionale, `?dividend=true`)* | Pagina landscape: tabella unificata con colonne SOTTOSTANTE / BARRIERE / DIVIDENDI a 2 livelli di header |
|
|
| **2 — Eventi** | Lista eventi cedole e autocall (tabella landscape multi-pagina) |
|
|
| **3 — Scenario** | Scenari di rendimento (opzionale, saltato se assente) |
|
|
| **4 — Grafico** | Performance storica dei sottostanti |
|
|
|
|
### Certificati non in quotazione (Stato = "Scaduto" / "Rimborsato" / "Revocato") — 3 sezioni (+1 opzionale)
|
|
|
|
| Sezione | Contenuto |
|
|
|---------|-----------|
|
|
| **1 — Anagrafica (semplificata)** | Header con solo Tipologia, caratteristiche con Valore/Data Rimborso, analisi KV, tabella sottostanti (omessa se `?dividend=true`) |
|
|
| **1b — Sottostanti e Dividendi** *(opzionale, `?dividend=true`)* | Pagina landscape: tabella unificata con colonne SOTTOSTANTE / BARRIERE / DIVIDENDI a 2 livelli di header |
|
|
| **2 — Eventi** | Lista eventi con colonne adattate (Barriera Cedola, Soglia Rimborso, Barriera Capitale, Rimborso Capitale) |
|
|
| **3 — Grafico** | Performance storica dei sottostanti |
|
|
|
|
Il tipo di report viene selezionato automaticamente dall'orchestratore in base al campo `Stato` restituito dalla SP `rpt_Master_CFT_ISIN`.
|
|
|
|
### Report ETF/Fondi — 2 pagine
|
|
|
|
| Pagina | Contenuto |
|
|
|--------|-----------|
|
|
| **1 — Anagrafica** | Title bar con Tipo/Nome/ISIN; strip Rank+Prezzo+Data; 3 colonne: **Dati Anagrafici** (Società, Categoria MS, Valuta, Hedged, Benchmark, Spese, Catalogo, Proventi, Data lancio, Patrimonio) · **ESG Score** (Sustainability, Environmental, Social, Governance) · **Griglia Performance/Volatilità/RendRisk** (3M, 6M, YTD, 1Y, 3Y, 5Y) |
|
|
| **2 — Grafico** | Storico prezzi close (linea singola, SkiaSharp), asse X con intervalli mensili adattivi |
|
|
|
|
SP: `sfih_GetOptDettagli` (anagrafica) · `sfih_GetChartPrices` (prezzi storici).
|
|
|
|
## API Endpoints
|
|
|
|
**Certificati:**
|
|
```
|
|
GET /api/report/by-isin/{ISIN} → PDF inline
|
|
GET /api/report?p={isin_cifrato} → PDF inline (ISIN cifrato)
|
|
GET /api/report?alias={id} → PDF inline (alias)
|
|
GET /api/report/download?p={...} → PDF come allegato
|
|
|
|
GET /api/chart/{isin} → Grafico standalone v1 (PNG/PDF)
|
|
GET /api/chart/v2/{isin} → Grafico standalone v2 (multi-formato, vedi sotto)
|
|
```
|
|
|
|
**ETF/Fondi:**
|
|
```
|
|
GET /api/report/fund/by-isin/{ISIN} → PDF inline
|
|
GET /api/report/fund?p={isin_cifrato} → PDF inline (ISIN cifrato)
|
|
GET /api/report/fund?alias={id} → PDF inline (alias)
|
|
GET /api/report/fund/download?p={...} → PDF come allegato
|
|
|
|
GET /api/chart/fund/{isin} → Grafico storico prezzi (PNG/JPEG/PDF)
|
|
```
|
|
|
|
```
|
|
GET /health → Health check DB + chart service
|
|
```
|
|
|
|
Parametri opzionali accettati da tutti gli endpoint report certificati:
|
|
|
|
| Parametro | Default | Effetto |
|
|
|-----------|---------|---------|
|
|
| `?branding=true` | `false` | Aggiunge footer "Powered by Smart Roots" con hyperlink |
|
|
| `?dividend=true` | `false` | Inserisce pagina landscape Sottostanti+Dividendi dopo la Sezione 1; omette la tabella sottostanti dalla Sezione 1 |
|
|
| `?natixis=true` | `false` | Box Tipologia mostra `info.Nome` invece di `info.Categoria` |
|
|
|
|
I parametri sono combinabili, es. `?branding=true÷nd=true&natixis=true`.
|
|
|
|
Parametri opzionali accettati dagli endpoint report **ETF/Fondi**:
|
|
|
|
| Parametro | Default | Effetto |
|
|
|-----------|---------|---------|
|
|
| `?branding=true` | `false` | Aggiunge footer "Powered by Smart Roots" con hyperlink |
|
|
|
|
### Grafico Fondi — parametri
|
|
|
|
```
|
|
GET /api/chart/fund/{isin}[?format=png|jpg|jpeg|pdf&width=&height=&save=true]
|
|
```
|
|
|
|
| Parametro | Valori | Effetto |
|
|
|-----------|--------|---------|
|
|
| `?format=` | `png` (default), `jpg`/`jpeg`, `pdf` | Formato output |
|
|
| `?save=true` | — | Salva JPEG su disco (`ChartSettings:SavePath/{isin}_fund.jpg`) — solo per `jpg`/`jpeg` |
|
|
|
|
### Grafico V2 — parametri
|
|
|
|
```
|
|
GET /api/chart/v2/{isin}[?format=png|jpg|jpeg|jpgEnc|pdf&width=&height=&save=true]
|
|
```
|
|
|
|
| Parametro | Valori | Effetto |
|
|
|-----------|--------|---------|
|
|
| `?format=` | `png` (default), `jpg`/`jpeg`, `jpgEnc`, `pdf` | Formato output; `jpgEnc` usa filename da alias SP; `pdf` genera PDF landscape |
|
|
| `?save=true` | — | Salva il JPEG su disco (percorsi da `ChartSettings:SavePath` / `SavePathEnc`) — solo per `jpg`/`jpeg`/`jpgEnc` |
|
|
|
|
**Colori grafico V2**: CTF = nero `#000000`, WorstOf = rosso `#CC0000`, altri sottostanti = palette vivace (teal/amber/viola/celeste…), Barriera Capitale = marrone `#715548`.
|
|
|
|
## Avvio locale
|
|
|
|
```bash
|
|
# Restore e build
|
|
dotnet restore
|
|
dotnet build
|
|
|
|
# Run
|
|
dotnet run --project CertReports.Syncfusion
|
|
# → https://localhost:{porta}/api/report/by-isin/{ISIN}
|
|
```
|
|
|
|
## Avvio con Docker
|
|
|
|
```bash
|
|
docker-compose up --build
|
|
# → http://localhost:5080/api/report/by-isin/{ISIN}
|
|
```
|
|
|
|
## Configurazione
|
|
|
|
| File | Scopo |
|
|
|------|-------|
|
|
| `appsettings.json` | Connection string (`CertDb`), Syncfusion license key, CryptoSettings passphrase, cache TTL |
|
|
| `appsettings.Development.json` | Override per sviluppo locale (non deve contenere `ConnectionStrings`) |
|
|
|
|
**Connection string SQL Server:**
|
|
```json
|
|
"ConnectionStrings": {
|
|
"CertDb": "Data Source=tcp:IP;Initial Catalog=FirstSolutionDB;User Id=...;Password=...;Encrypt=False;"
|
|
}
|
|
```
|
|
|
|
## Aggiungere una nuova sezione PDF
|
|
|
|
1. Implementare `IPdfSectionRenderer`
|
|
2. Impostare `SectionName` e `Order`
|
|
3. Registrare in `Program.cs`:
|
|
```csharp
|
|
builder.Services.AddScoped<IPdfSectionRenderer, NuovaSezione>();
|
|
```
|
|
L'orchestratore la include automaticamente ordinandola per `Order`.
|
|
|
|
## Tema grafico
|
|
|
|
Tutto il tema (colori, font, layout, brush/pen) è centralizzato in `CertReports.Syncfusion/Helpers/PdfTheme.cs`.
|
|
|
|
| Colore | Hex | Utilizzo |
|
|
|--------|-----|---------|
|
|
| AccentBlue | `#1565C0` | Titoli, header tabelle, valori chiave |
|
|
| NegativeRed | `#CC0000` | Valori negativi |
|
|
| PositiveGreen | `#2E7D32` | Valori positivi |
|
|
|
|
## Architettura
|
|
|
|
```
|
|
HTTP (ISIN) → ReportController → ReportOrchestrator
|
|
├── CertificateDataService (SP → anagrafica, sottostanti, eventi, scenario)
|
|
│
|
|
├── [Stato == "Quotazione"] ──────────────────────────────────────────
|
|
│ ├── AnagraficaSectionRenderer → PdfDocument (Sezione 1, senza tabella sottostanti se dividend=true)
|
|
│ ├── DividendSectionRenderer → PdfDocument (Sezione 1b, solo se ?dividend=true, landscape)
|
|
│ ├── EventiSectionRenderer → PdfDocument (Sezione 2)
|
|
│ ├── ScenarioSectionRenderer → PdfDocument (Sezione 3, opzionale)
|
|
│ └── ChartSectionRenderer → PdfDocument (Sezione 4)
|
|
│
|
|
├── [Stato != "Quotazione"] ─────────────────────────────────────────
|
|
│ ├── ExpiredAnagraficaSectionRenderer → PdfDocument (Sezione 1, senza tabella sottostanti se dividend=true)
|
|
│ ├── DividendSectionRenderer → PdfDocument (Sezione 1b, solo se ?dividend=true, landscape)
|
|
│ ├── EventiSectionRenderer → PdfDocument (Sezione 2, colonne adattate)
|
|
│ └── ChartSectionRenderer → PdfDocument (Sezione 3)
|
|
│
|
|
├── ChartDataService (SP → dati grafico v1)
|
|
├── SkiaChartRenderer → PNG in memoria (v1)
|
|
└── PdfMergerService → byte[] → Response
|
|
|
|
HTTP (ISIN) → ChartController → /api/chart/v2/{isin}
|
|
├── ChartDataServiceV2 (cedlab_Chart_UL1 + cedlab_Chart_AllSeriesV2)
|
|
└── SkiaChartRendererV2 → PNG/JPEG/PDF → Response (+ salvataggio disco se ?save=true)
|
|
|
|
HTTP (ISIN) → FundReportController → /api/report/fund/
|
|
├── FundDataService (sfih_GetOptDettagli + sfih_GetChartPrices)
|
|
├── FundReportOrchestrator
|
|
│ ├── FundAnagraficaRenderer → PdfDocument (Pagina 1: layout C)
|
|
│ ├── FundChartSectionRenderer → PdfDocument (Pagina 2: grafico landscape)
|
|
│ │ └── FundSkiaChartRenderer [static] → PNG in memoria
|
|
│ └── PdfMergerService → byte[] → Response
|
|
└── PdfCacheService (chiave fund:{isin}[:branded])
|
|
|
|
HTTP (ISIN) → FundChartController → /api/chart/fund/{isin}
|
|
├── FundDataService (sfih_GetOptDettagli + sfih_GetChartPrices, in parallelo)
|
|
└── FundSkiaChartRenderer [static] → PNG/JPEG/PDF → Response (+ salvataggio disco se ?save=true)
|
|
```
|
|
|
|
---
|
|
|
|
*Sviluppato da [Smart Roots](https://www.smart-roots.net)*
|