427 lines
21 KiB
Markdown
427 lines
21 KiB
Markdown
# CertReports.Syncfusion — Documentazione Tecnica
|
||
|
||
> Progetto ASP.NET Core 8 per la generazione di report PDF per certificati finanziari strutturati.
|
||
> Sostituisce il vecchio progetto WebForms basato su DevExpress (non licenziato) + PdfSharp.
|
||
> Utilizza **Syncfusion PDF Library** (Community License) e **SkiaSharp** per i grafici.
|
||
|
||
---
|
||
|
||
## 1. Panoramica
|
||
|
||
Il sistema riceve un codice ISIN (in chiaro, cifrato o tramite alias), interroga il database SQL Server tramite stored procedures, genera un report PDF composto da 4 sezioni e lo restituisce come stream inline al browser.
|
||
|
||
### Flusso di generazione
|
||
|
||
```
|
||
Richiesta HTTP (ISIN)
|
||
│
|
||
▼
|
||
ReportController ──→ decodifica ISIN (se cifrato)
|
||
│
|
||
▼
|
||
ReportOrchestrator
|
||
│
|
||
├──→ CertificateDataService
|
||
│ ├── rpt_Master_CFT_ISIN → Anagrafica certificato
|
||
│ ├── rpt_Details_UL_ISIN → Sottostanti
|
||
│ ├── rpt_Events_CFT_ISIN → Eventi
|
||
│ └── rpt_AnalisiScenario_ISIN → Analisi scenario
|
||
│
|
||
├──→ AnagraficaSectionRenderer → PDF Sezione 1
|
||
├──→ EventiSectionRenderer → PDF Sezione 2
|
||
├──→ ScenarioSectionRenderer → PDF Sezione 3 (se dati presenti)
|
||
│
|
||
├──→ ChartDataService
|
||
│ ├── FSWeb_Chart_UL → Info sottostanti grafico
|
||
│ ├── FSWeb_Chart_DailyCTF → Performance certificato
|
||
│ └── FSWeb_Chart_DailyUL → Performance sottostanti
|
||
│
|
||
├──→ ChartSectionRenderer → PDF Sezione 4 (SkiaSharp)
|
||
│ └── SkiaChartRenderer → Genera PNG in memoria
|
||
│
|
||
└──→ PdfMergerService → Unisce i PDF → byte[]
|
||
│
|
||
▼
|
||
Response PDF inline
|
||
```
|
||
|
||
---
|
||
|
||
## 2. Struttura del progetto
|
||
|
||
```
|
||
SmartReports/ ← Solution
|
||
└── CertReports.Syncfusion/ ← Progetto
|
||
├── Controllers/
|
||
│ ├── ReportController.cs ← API report PDF completo
|
||
│ └── ChartController.cs ← API chart standalone (PNG/PDF)
|
||
│
|
||
├── Helpers/
|
||
│ ├── CryptoHelper.cs ← Decodifica ISIN (ENCRYPTBYPASSPHRASE)
|
||
│ ├── GlobalExceptionMiddleware.cs ← Error handling centralizzato
|
||
│ ├── HealthChecks.cs ← Health check DB + Chart service
|
||
│ └── PdfTheme.cs ← Colori, font, stili, bordi (tema centralizzato)
|
||
│
|
||
├── Models/
|
||
│ ├── CertificateModels.cs ← Modelli report (anagrafica, eventi, scenario)
|
||
│ └── ChartModels.cs ← Modelli grafico (serie, punti, barriere)
|
||
│
|
||
├── Services/
|
||
│ ├── Interfaces/
|
||
│ │ └── IServices.cs ← Contratti DI per tutti i servizi
|
||
│ └── Implementations/
|
||
│ ├── CertificateDataService.cs ← Accesso DB: anagrafica, eventi, scenario
|
||
│ ├── ChartDataService.cs ← Accesso DB: dati grafico (3 SP)
|
||
│ ├── AnagraficaSectionRenderer.cs ← Sezione 1: anagrafica + sottostanti
|
||
│ ├── EventiSectionRenderer.cs ← Sezione 2: tabella eventi (multi-pagina)
|
||
│ ├── ScenarioSectionRenderer.cs ← Sezione 3: matrice scenario con gradiente
|
||
│ ├── ChartSectionRenderer.cs ← Sezione 4: inserisce chart PNG nel PDF
|
||
│ ├── SkiaChartRenderer.cs ← Genera il grafico con SkiaSharp
|
||
│ ├── PdfMergerService.cs ← Merge PDF con Syncfusion
|
||
│ ├── PdfCacheService.cs ← Cache in memoria (IMemoryCache)
|
||
│ └── ReportOrchestrator.cs ← Coordinatore principale
|
||
│
|
||
├── Program.cs ← Entry point, DI, middleware
|
||
├── GlobalUsings.cs ← Using globali
|
||
├── CertReports.Syncfusion.csproj ← Progetto + pacchetti NuGet
|
||
├── appsettings.json ← Configurazione produzione
|
||
├── appsettings.Development.json ← Override per sviluppo
|
||
├── Dockerfile ← Build containerizzata
|
||
├── docker-compose.yml ← Compose con SQL Server
|
||
└── .gitignore
|
||
```
|
||
|
||
---
|
||
|
||
## 3. Mapping vecchio → nuovo
|
||
|
||
| Vecchio (DevExpress / WebForms) | Nuovo (Syncfusion / ASP.NET Core 8) |
|
||
|----------------------------------------------|-------------------------------------------|
|
||
| `ReportFSSiteCrypt.aspx` (Page_Load) | `ReportController.cs` (API REST) |
|
||
| `XtraReport` + file `.repx` | Classi `IPdfSectionRenderer` (codice C#) |
|
||
| `report.ExportToPdf()` per ogni sezione | Ogni renderer restituisce `PdfDocument` |
|
||
| `PdfSharp.PdfReader.Open` + `CopyPages` | `PdfMergerService` (Syncfusion) |
|
||
| `CommonClass.DecryptCombined()` | `CryptoHelper.DecryptIsin()` |
|
||
| `CommonClass.execSP_Scalar()` | `CertificateDataService` (async) |
|
||
| `ChartFSWeb.aspx` (DevExpress WebChart) | `SkiaChartRenderer` + `ChartController` |
|
||
| `CallWebApi()` con `WebRequest` | Generazione interna (nessuna chiamata HTTP)|
|
||
| File temporanei su disco + `File.Delete` | Tutto in memoria (`MemoryStream`) |
|
||
| `Response.BinaryWrite()` | `return File(bytes, "application/pdf")` |
|
||
| `System.Data.SqlClient` | `Microsoft.Data.SqlClient` v5 |
|
||
|
||
---
|
||
|
||
## 4. Stored procedures utilizzate
|
||
|
||
Tutte le SP sono nel database `FirstSolutionDB`.
|
||
|
||
### Report (sezioni 1-3)
|
||
|
||
| SP | Parametro | Sezione | Descrizione |
|
||
|----|-----------|---------|-------------|
|
||
| `rpt_Master_CFT_ISIN` | `@ISIN varchar(12)` | 1 — Anagrafica | Dati certificato (1 record). Campi pre-formattati con `FORMAT()`. Join su Issuer, Category, BasketType, BarrierType + numerose `OUTER APPLY` per valori calcolati. |
|
||
| `rpt_Details_UL_ISIN` | `@ISIN varchar(12)` | 1 — Sottostanti | N record sottostanti con strike, last price, barriere, buffer, dividendi. Campi formattati con `FORMAT(...,'N3','it-IT')`. |
|
||
| `rpt_Events_CFT_ISIN` | `@ISIN varchar(50)` | 2 — Eventi | Lista eventi ordinata per data. Cedole, trigger, autocall, importi pagati. Campi formattati. Colonne Trigger Capitale e Valore Capitale escluse dal report. |
|
||
| `rpt_AnalisiScenario_ISIN` | `@ISIN varchar(50)` | 3 — Scenario | 7 righe UNION con label in `Descrizione` e 13 colonne di valori (`col1..col13`). Variazioni: -90%, -80%, -70%, -60%, -50%, -40%, -30%, -20%, -10%, 0%, +10%, +20%, +30%. Tutte stringhe pre-formattate. |
|
||
| `rpt_FindIsinbyAliasID` | `@AliasID` | Risoluzione | Restituisce l'ISIN dato un alias ID. |
|
||
|
||
### Grafico (sezione 4)
|
||
|
||
| SP | Parametri | Descrizione |
|
||
|----|-----------|-------------|
|
||
| `FSWeb_Chart_UL` | `@isin varchar(15)` | Info sottostanti per il grafico: IDCertificates, IDUnderlyings, StartDate, Strike, BarrieraCoupon, BarrieraCapitale, Nome. Restituisce dati solo se ci sono almeno 30 prezzi EOD. |
|
||
| `FSWeb_Chart_DailyCTF` | `@ISIN varchar(50)` | Performance giornaliera del certificato: `Px_date`, `Performance` (= PX_LAST_EOD / Nominal_amount × 100). |
|
||
| `FSWeb_Chart_DailyUL` | `@IDCertificates, @IDUnderlyings, @StartDate, @Strike` | Performance giornaliera di ogni sottostante: `Px_date`, `Performance` (= Px_close / Strike × 100). Usa Px_closeadj se AdjustedPrices=1. Filtra per date presenti nel certificato. |
|
||
|
||
### Nota sui dati formattati
|
||
|
||
Le SP restituiscono la maggior parte dei valori **già formattati come stringhe** (es. `FORMAT(value,'P2','it-IT')`, `FORMAT(value,'F2','it-IT')`). I modelli C# usano `string` per questi campi per evitare parsing e riformattazione non necessari. Solo `NominalValue`, `PrezzoEmissione`, `CpnPagati`, `CpnDaPagare`, `CpnInMemoria` sono `decimal?` perché servono come valori numerici nel rendering.
|
||
|
||
---
|
||
|
||
## 5. Endpoint API
|
||
|
||
### Generazione report PDF completo (inline nel browser)
|
||
|
||
```
|
||
GET /api/report?p={isin_cifrato}
|
||
GET /api/report?alias={alias_id}
|
||
GET /api/report/by-isin/{isin}
|
||
```
|
||
|
||
### Download report come allegato
|
||
|
||
```
|
||
GET /api/report/download?p={isin_cifrato}
|
||
GET /api/report/download?alias={alias_id}
|
||
```
|
||
|
||
### Grafico standalone (richiamabile da altri progetti)
|
||
|
||
```
|
||
GET /api/chart/{isin} → PNG inline
|
||
GET /api/chart/{isin}?format=png → PNG inline
|
||
GET /api/chart/{isin}?format=pdf → PDF inline
|
||
GET /api/chart/{isin}?width=1200&height=800 → Dimensioni custom
|
||
```
|
||
|
||
Parametri opzionali: `width` (400-2000, default 1100), `height` (300-1500, default 700), `format` (png/pdf, default png).
|
||
|
||
### Health check
|
||
|
||
```
|
||
GET /health
|
||
```
|
||
|
||
---
|
||
|
||
## 6. Configurazione
|
||
|
||
### appsettings.json
|
||
|
||
```json
|
||
{
|
||
"ConnectionStrings": {
|
||
"CertDb": "Data Source=INDIRIZZO_SERVER;Initial Catalog=FirstSolutionDB;Persist Security Info=True;User ID=sa;Password=***;TrustServerCertificate=True;Encrypt=False;"
|
||
},
|
||
"Syncfusion": {
|
||
"LicenseKey": "CHIAVE_COMMUNITY_SYNCFUSION"
|
||
},
|
||
"CryptoSettings": {
|
||
"Passphrase": "ddCE3hM9BNJXgwtj"
|
||
},
|
||
"ReportSettings": {
|
||
"CacheMinutes": 5
|
||
}
|
||
}
|
||
```
|
||
|
||
La sezione `ChartService` non è più necessaria: il grafico viene generato internamente.
|
||
|
||
### Note sulla connection string
|
||
|
||
- Usare `Data Source` (non `Server`) e `Initial Catalog` (non `Database`) per compatibilità con `Microsoft.Data.SqlClient` v5
|
||
- Aggiungere `Encrypt=False;` se il SQL Server non ha SSL configurato
|
||
- Se la connessione non funziona via TCP, aggiungere il prefisso `tcp:` all'indirizzo (es. `Data Source=tcp:26.69.45.60;`)
|
||
|
||
### appsettings.Development.json
|
||
|
||
Non deve contenere `ConnectionStrings` — altrimenti sovrascrive i valori di `appsettings.json`. Contiene solo override per logging e cache in sviluppo.
|
||
|
||
---
|
||
|
||
## 7. Pacchetti NuGet
|
||
|
||
| Pacchetto | Versione | Scopo |
|
||
|-----------|----------|-------|
|
||
| `Syncfusion.Pdf.Net.Core` | 33.x | Generazione e merge PDF |
|
||
| `Microsoft.Data.SqlClient` | 5.x | Accesso SQL Server |
|
||
| `SkiaSharp` | 2.x | Generazione grafico server-side |
|
||
| `Serilog.AspNetCore` | 8.x | Logging strutturato |
|
||
| `Serilog.Sinks.File` | 5.x | Log su file con rotazione giornaliera |
|
||
|
||
### Note
|
||
|
||
- `Syncfusion.Drawing.Net.Core` **non esiste più** nella v33: è inglobato in `Syncfusion.Pdf.Net.Core`
|
||
- Per i colori usare `Color.FromArgb(255, r, g, b)` invece di `new Color(r, g, b)` (cambiamento v33)
|
||
- `PdfStandardFont` **non è IDisposable** in Syncfusion v33: non usare `using` nella dichiarazione
|
||
- SkiaSharp v2.x: usare `SKFont` per dimensione/typeface e `canvas.DrawText(text, x, y, SKTextAlign, font, paint)` — le API su `SKPaint` sono obsolete
|
||
|
||
---
|
||
|
||
## 8. Architettura e pattern
|
||
|
||
### Dependency Injection
|
||
|
||
Tutti i servizi sono registrati in `Program.cs`:
|
||
|
||
- `ICertificateDataService` → `CertificateDataService` (Scoped)
|
||
- `IChartDataService` → `ChartDataService` (Scoped)
|
||
- `IPdfSectionRenderer` → registrati multipli: `Anagrafica`, `Eventi`, `Scenario` (Scoped)
|
||
- `IChartSectionRenderer` → `ChartSectionRenderer` (Scoped)
|
||
- `IPdfMergerService` → `PdfMergerService` (Scoped)
|
||
- `IReportOrchestrator` → `ReportOrchestrator` (Scoped)
|
||
- `IPdfCacheService` → `PdfCacheService` (Singleton)
|
||
- `CryptoHelper` (Singleton)
|
||
|
||
### Aggiungere una nuova sezione al report
|
||
|
||
1. Creare una classe che implementa `IPdfSectionRenderer`
|
||
2. Assegnare `SectionName` e `Order` (determina la posizione nel PDF)
|
||
3. Implementare `Render(CertificateReportData data)` che restituisce un `PdfDocument`
|
||
4. Registrarla in `Program.cs`: `builder.Services.AddScoped<IPdfSectionRenderer, NuovaSezione>();`
|
||
|
||
L'orchestratore la includerà automaticamente nel report, ordinata per `Order`.
|
||
|
||
### Tema e stili
|
||
|
||
`PdfTheme.cs` centralizza:
|
||
|
||
- **Colori**: `HeaderBackground`, `AlternateRow`, `PositiveValue`, `NegativeValue`, ecc.
|
||
- **Font**: `Regular` (8pt), `Bold`, `Small` (6.5pt), `Title` (14pt), `Header` (7pt bold)
|
||
- **Layout**: `PageMargin` (40pt), `RowHeight` (18pt), `CellPadding` (4pt)
|
||
- **Brushes e Pens**: pronti all'uso, derivati dai colori
|
||
- **Bordi**: `ApplyThinBorders(grid, thickness)` per linee tabella sottili e uniformi
|
||
|
||
Modificare un valore in `PdfTheme` aggiorna tutti i renderer automaticamente.
|
||
|
||
### Bordi tabelle
|
||
|
||
Tutte le tabelle PdfGrid usano `PdfTheme.ApplyThinBorders(grid)` prima del `Draw()` per ottenere linee sottili e uniformi (0.25pt di default). Il metodo itera su headers e righe applicando `PdfBorders` con `PdfPen` del colore e spessore definiti nel tema.
|
||
|
||
### Cache
|
||
|
||
I PDF generati vengono memorizzati in `IMemoryCache` per `CacheMinutes` (default 5 minuti, configurabile). Evita rigenerazioni per ricaricamenti di pagina. La cache ha un limite di 200 MB totali.
|
||
|
||
### Gestione errori
|
||
|
||
`GlobalExceptionMiddleware` cattura tutte le eccezioni non gestite e restituisce risposte JSON coerenti con status code appropriati (400, 404, 408, 500).
|
||
|
||
---
|
||
|
||
## 9. Sezione grafico (Sezione 4)
|
||
|
||
Il grafico viene generato **interamente in memoria** con SkiaSharp, eliminando la dipendenza dall'endpoint esterno `ChartFSWeb.aspx`.
|
||
|
||
### Architettura
|
||
|
||
```
|
||
ChartSectionRenderer
|
||
│
|
||
├──→ ChartDataService ← Recupera dati da DB (3 SP)
|
||
│
|
||
└──→ SkiaChartRenderer ← Genera PNG con SkiaSharp
|
||
│
|
||
└──→ PNG in memoria → inserito nel PDF come PdfBitmap
|
||
```
|
||
|
||
### Cosa disegna il grafico
|
||
|
||
- **Serie certificato**: linea nera, spessore 2.5px (performance % nel tempo)
|
||
- **Serie sottostanti**: N linee colorate, spessore 1.5px (ciascuna con colore diverso dal palette ciclico)
|
||
- **Barriera Capitale**: linea orizzontale rossa
|
||
- **Barriera Coupon**: linea orizzontale viola (solo se diversa da Barriera Capitale)
|
||
- **Strike (100%)**: linea orizzontale verde
|
||
- **Asse Y**: percentuale con auto-scaling e margine 10%
|
||
- **Asse X**: date con step automatico (trimestrale/semestrale/annuale)
|
||
- **Legenda**: box in alto a destra con tutte le serie e le linee costanti
|
||
- **Griglia**: linee orizzontali e verticali grigio chiaro
|
||
|
||
### API chart standalone
|
||
|
||
Il `ChartController` espone il grafico come API indipendente, richiamabile da qualsiasi altro progetto senza passare per il report completo.
|
||
|
||
---
|
||
|
||
## 10. Sezione scenario (Sezione 3)
|
||
|
||
### Stile visivo
|
||
|
||
La sezione scenario replica lo stile del vecchio report DevExpress:
|
||
|
||
- **Header con gradiente colore**: da rosso scuro (-90%) attraverso arancio e giallo fino a verde (+30%)
|
||
- **Testo header bianco** su sfondo colorato
|
||
- **Titolo "Analisi Scenario"** centrato, grande, colore blu
|
||
- **Righe alternate** con sfondo grigio chiaro
|
||
- **Valori negativi** in rosso scuro
|
||
- **13 colonne di variazione**: -90%, -80%, -70%, -60%, -50%, -40%, -30%, -20%, -10%, 0%, +10%, +20%, +30%
|
||
|
||
### Logica di inclusione
|
||
|
||
La sezione scenario viene inclusa nel report se `rpt_AnalisiScenario_ISIN` restituisce almeno una riga. La condizione è semplicemente `scenario.Rows.Count > 0` (non controlla i valori, perché la SP restituisce anche `"--"` per dati non calcolabili).
|
||
|
||
---
|
||
|
||
## 11. Deploy
|
||
|
||
### Locale (Visual Studio)
|
||
|
||
```
|
||
F5 → https://localhost:{porta}/api/report/by-isin/{ISIN}
|
||
F5 → https://localhost:{porta}/api/chart/{ISIN}
|
||
```
|
||
|
||
### Docker
|
||
|
||
```bash
|
||
docker-compose up --build
|
||
# → http://localhost:5080/api/report/by-isin/{ISIN}
|
||
# → http://localhost:5080/api/chart/{ISIN}
|
||
```
|
||
|
||
Il `Dockerfile` include l'installazione dei font necessari per il rendering PDF e SkiaSharp (`libfontconfig1`, `fonts-dejavu-core`) e gira come utente non-root per sicurezza.
|
||
|
||
---
|
||
|
||
## 12. Logging
|
||
|
||
Serilog scrive su:
|
||
|
||
- **Console**: tutti i log in tempo reale
|
||
- **File**: `Logs/certreports-{data}.log` con rotazione giornaliera
|
||
|
||
Livelli configurabili in `appsettings.json`. In Development il livello di default è `Debug`, in Production è `Information`.
|
||
|
||
Ogni step del flusso è loggato:
|
||
|
||
```
|
||
[INF] Richiesta report per ISIN CH1277653163
|
||
[DBG] Cache MISS per ISIN CH1277653163
|
||
[INF] Inizio generazione report per ISIN CH1277653163
|
||
[INF] Anagrafica caricata per CH1277653163: Leonteq, 3 sottostanti
|
||
[INF] Eventi caricati per CH1277653163: 36 eventi
|
||
[INF] Scenario caricato per CH1277653163: 7 righe
|
||
[INF] Sezione 'Anagrafica' generata per CH1277653163
|
||
[INF] Sezione 'Eventi' generata per CH1277653163
|
||
[INF] Sezione 'Scenario' generata per CH1277653163
|
||
[INF] Dati grafico caricati per CH1277653163: 4 serie, certificato 650 punti
|
||
[INF] Grafico generato per CH1277653163: 82450 bytes PNG, 4 serie
|
||
[INF] Sezione Grafico aggiunta per CH1277653163
|
||
[INF] Report generato per CH1277653163: 125000 bytes, 4 sezioni
|
||
[DBG] Cache SET per CH1277653163 (125000 bytes, TTL 5min)
|
||
```
|
||
|
||
---
|
||
|
||
## 13. Problemi noti e soluzioni
|
||
|
||
| Problema | Causa | Soluzione |
|
||
|----------|-------|-----------|
|
||
| `Cannot access a closed Stream` nel merge | Gli stream dei `PdfLoadedDocument` venivano chiusi prima del `Save()` finale | `PdfMergerService` tiene tutti gli stream aperti fino al salvataggio, poi fa cleanup nel `finally` |
|
||
| `Color does not contain a constructor that takes 3 arguments` | Syncfusion v33 ha rimosso `new Color(r,g,b)` | Usare `Color.FromArgb(255, r, g, b)` |
|
||
| `Syncfusion.Drawing.Net.Core` non trovato | Pacchetto rimosso nella v33, inglobato in `Syncfusion.Pdf.Net.Core` | Rimuovere dal `.csproj` |
|
||
| `Unexpected character '{'` in `FormatPercent` | Interpolazione annidata non supportata in C# | Usare `value.Value.ToString($"N{decimals}") + " %"` |
|
||
| Connessione DB via Named Pipes | `Microsoft.Data.SqlClient` v5 tenta Named Pipes di default | Aggiungere `Encrypt=False;` e/o prefisso `tcp:` nella connection string |
|
||
| Connection string ignorata | `appsettings.Development.json` sovrascriveva `appsettings.json` | Rimuovere `ConnectionStrings` da `appsettings.Development.json` |
|
||
| Scenario mai generato | SP sbagliata (`rpt_AnalisiRischio_ISIN` con 11 colonne) e check troppo restrittivo | Usare `rpt_AnalisiScenario_ISIN` (13 colonne, label in `Descrizione`), condizione `Rows.Count > 0` |
|
||
| Namespace conflict `Syncfusion.Pdf` in `ChartController` | `CertReports.Syncfusion.Pdf` confuso con `Syncfusion.Pdf` | Aggiungere `using Syncfusion.Pdf;` esplicito, non usare riferimenti fully-qualified |
|
||
| `PdfStandardFont` non è IDisposable | Syncfusion v33 non implementa `IDisposable` su questo tipo | Non usare `using` nella dichiarazione |
|
||
| SkiaSharp `DrawText` obsoleto | `SKPaint.TextSize/Typeface` deprecati in SkiaSharp 2.x | Usare `SKFont` + `canvas.DrawText(text, x, y, SKTextAlign, font, paint)` |
|
||
| Bordi tabelle troppo spessi | `PdfGrid` usa bordi di default grossi | `PdfTheme.ApplyThinBorders(grid)` con `PdfPen` a 0.25pt prima di `Draw()` |
|
||
| `grid.Headers` non iterabile con foreach | Syncfusion v33 non espone `IEnumerable` sugli headers | Usare `for (int r = 0; r < grid.Headers.Count; r++)` con accesso indicizzato |
|
||
| `grid.Draw()` restituisce void | Syncfusion v33 ha rimosso il valore di ritorno | Stimare altezza con `(grid.Rows.Count + 1) * RowHeight` |
|
||
|
||
---
|
||
|
||
## 14. Cronologia modifiche
|
||
|
||
| Data | Modifica |
|
||
|------|----------|
|
||
| 18/03/2026 | Creazione progetto iniziale con struttura ASP.NET Core 8 + Syncfusion |
|
||
| 18/03/2026 | Implementazione completa `CryptoHelper.DecryptCombined` (v1 TripleDES + v2 AES) |
|
||
| 18/03/2026 | Mapping SP reali: `rpt_Master_CFT_ISIN`, `rpt_Details_UL_ISIN`, `rpt_Events_CFT_ISIN` |
|
||
| 18/03/2026 | Fix compatibilità Syncfusion v33: `Color.FromArgb`, rimozione `Syncfusion.Drawing.Net.Core` |
|
||
| 18/03/2026 | Fix `PdfMergerService`: stream mantenuti aperti fino al `Save()` finale |
|
||
| 18/03/2026 | Fix connection string: `Data Source` + `Encrypt=False` per `Microsoft.Data.SqlClient` v5 |
|
||
| 18/03/2026 | Fix `appsettings.Development.json` che sovrascriveva la connection string |
|
||
| 18/03/2026 | Prima generazione PDF riuscita con dati reali |
|
||
| 18/03/2026 | Porting grafico da DevExpress `ChartFSWeb.aspx` a SkiaSharp interno |
|
||
| 18/03/2026 | Aggiunta `ChartDataService` (SP: `FSWeb_Chart_UL`, `FSWeb_Chart_DailyCTF`, `FSWeb_Chart_DailyUL`) |
|
||
| 18/03/2026 | Aggiunta `SkiaChartRenderer` con serie, barriere, legenda, auto-scaling |
|
||
| 18/03/2026 | Aggiunta `ChartController` per API chart standalone (`/api/chart/{isin}`) |
|
||
| 18/03/2026 | Fix scenario: SP corretta `rpt_AnalisiScenario_ISIN` con 13 colonne e label `Descrizione` |
|
||
| 18/03/2026 | Scenario: header con gradiente rosso→verde, valori negativi in rosso |
|
||
| 18/03/2026 | Rimozione colonne Trigger Capitale e Valore Capitale dalla tabella eventi |
|
||
| 18/03/2026 | Fix bordi tabelle: `PdfTheme.ApplyThinBorders()` con linee 0.25pt |
|
||
| 18/03/2026 | Fix SkiaSharp: migrazione a API moderna `SKFont` (rimozione warning obsoleti) |
|