fix: null-safe string reader, chart V2 label collision avoidance
- ChartDataServiceV2: aggiunto helper ToStr() per GetString null-safe su colonne nullable (Sottostante, NomeCFT); pattern analogo a ToDecimal - SkiaChartRendererV2: collision avoidance label margine destro — tutti i label (barriere, strike, autocall, end-label serie) raccolti in lista, ordinati per Y e distribuiti con spacing minimo 13px (push-down + clamp-up) prima del disegno - CLAUDE.md: documentati i due fix e la root cause cedlab_Chart_UL1 divide-by-zero su Strike=0 (fix DB: NULLIF(cu.Strike,0)) Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -86,6 +86,8 @@ HTTP (ISIN) → ReportController → ReportOrchestrator
|
||||
| Namespace conflict `CertReports.Syncfusion.Pdf` | Aggiungere `using Syncfusion.Pdf;` esplicito nel file |
|
||||
| SkiaSharp `SKFont` NON è IDisposable | Non usare `using` su `SKFont` — solo `SKPaint`, `SKPath`, `SKSurface`, `SKImage`, `SKData` sono IDisposable |
|
||||
| `SqlDataReader.GetDecimal` su colonna `float` SQL | Usare `Convert.ToDecimal(r.GetValue(ord))` — le SP cedlab_ possono restituire `float` (es. `PriceWorst` da subquery su `Prices.Px_close`) |
|
||||
| `SqlDataReader.GetString` su colonna nullable | Usare `ToStr(r, column)` (helper in `ChartDataServiceV2`) che fa `r.IsDBNull` prima — `GetString` su `DBNull` lancia `SqlNullValueException` |
|
||||
| `cedlab_Chart_UL1`: Divide by zero su `Strike = 0` | La SP divide per `cu.Strike` senza guard nel calcolo `PriceWorstPerc`. Fix applicato nel DB: `/ NULLIF(cu.Strike, 0)`. Colpisce certificati con Strike non impostato in `CertificatesUnderlyings` |
|
||||
|
||||
## Grafico V2 (`/api/chart/v2/{isin}`)
|
||||
|
||||
@@ -126,6 +128,8 @@ Percorsi configurati in `appsettings.json` → `ChartSettings:SavePath` e `Chart
|
||||
|
||||
**Note renderer**: CTF non mostrato se `NumPrezziCFT < 30` (mostra solo avviso testo); asse X usa intervalli mensili adattivi (12m/6m/3m/1m in base al range).
|
||||
|
||||
**Label destra — collision avoidance**: i label sul margine destro (barriere, strike, autocall, end-label serie) vengono raccolti in una lista `rightLabels`, ordinati per Y, e disegnati da `DrawRightLabels` con spacing minimo 13px. Due passate: discendente (push-down) + risalente (clamp al bordo area). Questo evita la sovrapposizione quando una serie si accavalla con una linea costante.
|
||||
|
||||
## Database
|
||||
|
||||
Tutte le stored procedure sono su `FirstSolutionDB`. I dati tornano **già formattati come stringhe** dalle SP (es. `FORMAT(value,'P2','it-IT')`): i modelli C# usano `string` per questi campi. Solo `NominalValue`, `PrezzoEmissione`, `CpnPagati`, `CpnDaPagare`, `CpnInMemoria` sono `decimal?` perché servono come valori numerici nel rendering.
|
||||
|
||||
Reference in New Issue
Block a user