# DEVELOPMENT.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
---
## ISTRUZIONI OBBLIGATORIE PER CLAUDE
### Auto-Aggiornamento DEVELOPMENT.md
**OBBLIGATORIO:** Claude DEVE aggiornare questo file DEVELOPMENT.md ogni volta che:
1. **Viene completato un task significativo** (fix, nuova feature, refactoring importante)
2. **Viene risolto un problema tecnico** che potrebbe ripresentarsi in futuro
3. **Si scopre un pattern/workaround** importante da ricordare
4. **Termina una sessione di lavoro** - aggiornare "Quick Start - Session Recovery"
**Cosa aggiornare:**
- **Sezione "Quick Start - Session Recovery":**
- Aggiornare "Ultima sessione" con data corrente
- Spostare lavoro completato da "ultima sessione" a "sessioni precedenti"
- Aggiungere nuovi task completati alla lista
- Aggiornare "Prossimi task prioritari" (spuntare completati, aggiungere nuovi)
- **Sezione "Problemi Risolti (da ricordare)":**
- Aggiungere OGNI problema tecnico risolto con:
- Descrizione del problema
- Causa root
- Soluzione implementata
- File coinvolti
- **Checklist:**
- Aggiornare checkbox `[x]` per task completati
- Aggiungere nuovi task se scoperti durante il lavoro
**Formato per nuovi problemi risolti:**
```markdown
XX. **Nome Problema (FIX/IMPLEMENTATO DATA):** - **Problema:** Descrizione breve - **Causa:** Perché succedeva - **Soluzione:** Come è stato risolto - **File:** File modificati
```
**NON dimenticare:** Questo file è la memoria persistente tra sessioni. Se non viene aggiornato, il lavoro fatto andrà perso e dovrà essere riscoperto.
---
## Quick Start - Session Recovery
**Ultima sessione:** 29 Novembre 2025 (pomeriggio)
**Stato progetto:** Migrazione Oracle APEX → .NET + React TypeScript in corso
**Lavoro completato nell'ultima sessione:**
- **NUOVA FEATURE: Gestione Inventario (Frontend)** - COMPLETATO
- **Obiettivo:** Interfaccia utente per la gestione completa degli inventari fisici
- **Frontend implementato:**
- `InventoryListPage.tsx` - Lista inventari con stato, filtri e indicatori di progresso
- `InventoryFormPage.tsx` - Form per creazione e modifica testata inventario (con gestione stati)
- `InventoryCountPage.tsx` - Pagina di conteggio con griglia editabile, calcolo differenze live
- Aggiornati `routes.tsx` e `pages/index.ts` per includere le nuove rotte
- **Funzionalità:**
- Creazione inventari (Completo, Parziale per categoria/magazzino)
- Workflow stati: Bozza -> In Corso -> Completato -> Confermato
- Avvio inventario: generazione automatica righe basata su giacenza teorica
- Conteggio: inserimento quantità rilevate, evidenziazione differenze
- Conferma: generazione automatica movimenti di rettifica (positivo/negativo)
- **Integrazione:**
- Utilizza `inventoryService` per comunicare con `InventoryController`
- Gestione date con `dayjs`
- UI coerente con Material-UI e DataGrid
- **FIX: Tasto Inventario in Dashboard Magazzino** - RISOLTO
- **Problema:** Il tasto "Inventario" nelle azioni rapide portava a una pagina 404 (`/warehouse/inventories/new`)
- **Causa:** Errore nel hook `useWarehouseNavigation` che usava il plurale `inventories` invece del singolare `inventory` definito nelle rotte
- **Soluzione:** Corretti i percorsi in `useWarehouseNavigation.ts` per corrispondere a `routes.tsx`
- **File modificati:** `frontend/src/modules/warehouse/hooks/useWarehouseNavigation.ts`
- **FIX: Campo Codice Readonly e Codice Alternativo** - COMPLETATO
- **Obiettivo:** Il campo "Codice" deve essere sempre auto-generato (non modificabile), aggiungere campo "Codice Alternativo" opzionale
- **Backend modificato:**
- `WarehouseArticle.cs` - Aggiunto `AlternativeCode`
- `WarehouseLocation.cs` - Aggiunto `AlternativeCode`
- `WarehouseArticleCategory.cs` - Aggiunto `AlternativeCode`
- `Cliente.cs` - Aggiunto `Codice` e `CodiceAlternativo`
- `Articolo.cs` - Aggiunto `CodiceAlternativo`
- `AutoCodeService.cs` - Aggiornato per gestire unicità `Cliente.Codice`
- `ClientiController.cs` - Auto-generazione codice alla creazione
- `ArticoliController.cs` - Auto-generazione codice alla creazione
- `WarehouseArticlesController.cs` - Fix DTOs per rimuovere `Code` obbligatorio:
- `CreateArticleDto` - Rimosso `Code`, aggiunto `AlternativeCode`
- `UpdateArticleDto` - Rimosso `Code`, aggiunto `AlternativeCode`
- `ArticleDto` - Aggiunto `AlternativeCode`
- `MapFromDto` - Rimossa assegnazione Code (generato da service)
- `UpdateFromDto` - Rimossa modifica Code (immutabile)
- Migration `AddAlternativeCodeFields` creata e applicata
- **Frontend modificato:**
- `frontend/src/modules/warehouse/types/index.ts` - Aggiunto `alternativeCode` ai DTOs
- `frontend/src/types/index.ts` - Aggiunto `codice` e `codiceAlternativo` a Cliente/Articolo
- `ArticleFormPage.tsx` - Campo Codice readonly con "(Generato al salvataggio)"
- `WarehouseLocationsPage.tsx` - Campo Codice readonly
- `ArticoliPage.tsx` - Campo Codice readonly
- `ClientiPage.tsx` - Campo Codice readonly
- **Comportamento UI:**
- In creazione: campo Codice mostra "(Generato al salvataggio)" in corsivo
- In modifica: campo Codice mostra il valore reale, sempre disabled
- Campo "Codice Alternativo" sempre modificabile (opzionale)
**Lavoro completato nelle sessioni precedenti (30 Novembre 2025):**
- **NUOVA FEATURE: Sistema Codici Automatici Configurabili** - COMPLETATO
- **Obiettivo:** Sistema admin per configurare la generazione automatica di codici (articoli, magazzini, movimenti, ecc.)
- **Backend implementato:**
- `AutoCode.cs` - Entity con pattern configurabile, prefisso, sequenza, reset periodico
- `AutoCodeService.cs` - Logica business (generazione, preview, reset, validazione pattern)
- `AutoCodesController.cs` - API REST complete
- Migration EF Core `AddAutoCodeSystem`
- Seed automatico configurazioni default per tutte le entità
- **Frontend implementato:**
- `autoCode.ts` - Types TypeScript
- `autoCodeService.ts` - API calls
- `AutoCodesAdminPage.tsx` - Pagina admin con tabella configurazioni, dialog modifica, guida pattern
- **Pattern supportati:**
- `{PREFIX}` - Prefisso configurabile
- `{SEQ:n}` - Sequenza numerica con n cifre
- `{YYYY}`, `{YY}` - Anno
- `{MM}`, `{DD}` - Mese, Giorno
- **Funzionalità:**
- Configurazione per entità (warehouse_article, stock_movement, cliente, evento, ecc.)
- Reset sequenza annuale o mensile automatico
- Preview prossimo codice senza incremento
- Reset manuale sequenza
- Abilitazione/disabilitazione per entità
- Raggruppamento per modulo nell'UI
- **API Endpoints:**
- `GET /api/autocodes` - Lista configurazioni
- `GET /api/autocodes/{entityCode}` - Dettaglio
- `GET /api/autocodes/{entityCode}/preview` - Anteprima prossimo codice
- `POST /api/autocodes/{entityCode}/generate` - Genera nuovo codice
- `PUT /api/autocodes/{id}` - Aggiorna configurazione
- `POST /api/autocodes/{entityCode}/reset-sequence` - Reset sequenza
- `GET /api/autocodes/placeholders` - Lista placeholder disponibili
- **File principali:**
- `src/Apollinare.Domain/Entities/AutoCode.cs`
- `src/Apollinare.API/Services/AutoCodeService.cs`
- `src/Apollinare.API/Controllers/AutoCodesController.cs`
- `frontend/src/pages/AutoCodesAdminPage.tsx`
**Lavoro completato nelle sessioni precedenti (29 Novembre 2025 notte):**
- **NUOVA FEATURE: Modulo Magazzino (warehouse)** - COMPLETATO
- **Backend implementato:**
- Entities complete in `/src/Apollinare.Domain/Entities/Warehouse/`:
- `WarehouseLocation.cs` - Magazzini fisici/logici con Type enum (Physical, Virtual, Transit)
- `WarehouseArticleCategory.cs` - Categorie gerarchiche con Color, Icon, Level, FullPath
- `WarehouseArticle.cs` - Articoli con batch/serial management flags, valorizzazione
- `ArticleBatch.cs` - Tracciabilità lotti con scadenza
- `ArticleSerial.cs` - Tracciabilità numeri seriali
- `StockLevel.cs` - Giacenze per articolo/magazzino/batch
- `StockMovement.cs` - Movimenti (Inbound/Outbound/Transfer/Adjustment)
- `StockMovementLine.cs` - Righe movimento
- `MovementReason.cs` - Causali movimento
- `ArticleBarcode.cs` - Multi-barcode support
- `StockValuation.cs` + `StockValuationLayer.cs` - Valorizzazione periodo e layer FIFO/LIFO
- `InventoryCount.cs` + `InventoryCountLine.cs` - Inventari fisici
- Service completo `WarehouseService.cs` con:
- CRUD articoli, categorie, magazzini
- Gestione movimenti (carico/scarico/trasferimento/rettifica)
- Conferma movimenti con aggiornamento giacenze
- Calcolo valorizzazione (WeightedAverage, FIFO, LIFO, StandardCost)
- Gestione partite e seriali
- Controllers REST in `/src/Apollinare.API/Modules/Warehouse/Controllers/`:
- `WarehouseLocationsController.cs`
- `WarehouseArticlesController.cs`
- `WarehouseArticleCategoriesController.cs`
- `StockMovementsController.cs`
- `StockLevelsController.cs`
- Seed dati default (magazzino principale + transito, categorie base, causali)
- **CONFIGURAZIONE: EF Core Code First Migrations** - COMPLETATO
- **Problema:** Le tabelle venivano create manualmente invece che con migrations EF Core
- **Soluzione implementata:**
- Sostituito `db.Database.EnsureCreated()` con `db.Database.MigrateAsync()` in `Program.cs`
- Creata migration `InitialCreate` con tutte le tabelle (sistema + moduli + warehouse)
- Le migrations vengono applicate **automaticamente all'avvio** dell'applicazione
- Logging delle migrations pendenti prima dell'applicazione
- **Comandi per future migrations:**
```bash
# Creare nuova migration
dotnet ef migrations add NomeMigration \
--project src/Apollinare.Infrastructure \
--startup-project src/Apollinare.API
# L'applicazione è AUTOMATICA all'avvio - non serve "dotnet ef database update"
```
- **File modificati:** `Program.cs`, `src/Apollinare.Infrastructure/Migrations/`
**Lavoro completato nelle sessioni precedenti (29 Novembre 2025 sera):**
- **NUOVA FEATURE: Sistema Moduli Applicativi** - COMPLETATO (continuazione)
- **Obiettivo:** Sistema di modularizzazione per gestire licenze, abbonamenti e funzionalità dinamiche
- **Backend implementato:**
- `AppModule.cs` - Entity per definizione moduli (code, name, description, icon, basePrice, dependencies, etc.)
- `ModuleSubscription.cs` - Entity per stato abbonamento (isEnabled, subscriptionType, startDate, endDate, autoRenew)
- `ModuleService.cs` - Logica business (enable/disable, check dipendenze, gestione scadenze, cache)
- `ModulesController.cs` - API REST complete con DTOs
- Tabelle SQLite create manualmente (AppModules, ModuleSubscriptions)
- Seed automatico 5 moduli: warehouse, purchases, sales, production, quality
- **Frontend implementato:**
- `module.ts` - Types TypeScript (ModuleDto, SubscriptionDto, enums, helpers)
- `moduleService.ts` - API calls
- `ModuleContext.tsx` - React Context con hooks (useModules, useModuleEnabled, useActiveModules)
- `ModuleGuard.tsx` - Componente per proteggere route
- `ModulesAdminPage.tsx` - Pagina amministrazione moduli con cards, toggle, dettagli subscription
- `ModulePurchasePage.tsx` - Pagina acquisto/attivazione modulo con selezione piano
- **Integrazione:**
- `App.tsx` - ModuleProvider wrappa l'app, route /modules e /modules/purchase/:code
- `Layout.tsx` - Voce menu "Moduli" aggiunta
- **API Endpoints:**
- `GET /api/modules` - Lista tutti i moduli
- `GET /api/modules/active` - Solo moduli attivi
- `GET /api/modules/{code}` - Dettaglio modulo
- `GET /api/modules/{code}/enabled` - Verifica stato
- `PUT /api/modules/{code}/enable` - Attiva modulo
- `PUT /api/modules/{code}/disable` - Disattiva modulo
- `GET /api/modules/subscriptions` - Lista subscription
- `PUT /api/modules/{code}/subscription` - Aggiorna subscription
- `POST /api/modules/{code}/subscription/renew` - Rinnova
- `GET /api/modules/expiring` - Moduli in scadenza
- **Funzionalità:**
- Gestione dipendenze tra moduli (es. purchases richiede warehouse)
- Blocco disattivazione se altri moduli dipendono
- Abbonamenti mensili/annuali con date scadenza
- Auto-rinnovo opzionale
- Cache con invalidazione automatica
- Alert moduli in scadenza
**Lavoro completato nelle sessioni precedenti (29 Novembre 2025 mattina):**
- **NUOVA FEATURE: Sistema Pannelli Drag-and-Drop con Sidebar Ridimensionabili** - COMPLETATO
- **Obiettivo:** I pannelli del report designer devono poter essere trascinati tra sidebar sinistra e destra, con ridimensionamento orizzontale a livello sidebar
- **Architettura implementata:**
- `SidebarDropZone.tsx` - Contenitore sidebar con:
- Drop zone per drag-and-drop pannelli (HTML5 Drag and Drop API)
- Handle di resize orizzontale sul bordo interno
- Indicatore visivo durante il drag
- Props: `position`, `width`, `onWidthChange`, `onPanelDrop`, `panelIds`
- `ResizablePanel.tsx` - Pannello individuale con:
- Header trascinabile (`draggable="true"`)
- Resize verticale (flex) tra pannelli nella stessa sidebar
- Stato collassato con icona e titolo verticale
- `width: 100%` - si adatta alla larghezza della sidebar
- `usePanelLayout.ts` - Hook per gestione stato:
- `sidebarWidths: { left: number, right: number }` per larghezza sidebar
- `panels[]` con `flex` per distribuzione verticale
- `movePanelToPosition()` redistribuisce flex quando un pannello viene droppato
- Persistenza in localStorage (versione 3)
- **Comportamento:**
- Trascinando l'header di un pannello si può spostarlo tra sidebar
- Quando un pannello viene droppato, tutti i pannelli nella sidebar di destinazione ottengono `flex: 1` (distribuzione equa)
- Il resize orizzontale agisce sulla sidebar intera, non sui singoli pannelli
- I pannelli adottano automaticamente la larghezza della sidebar
- **Layout Full-Width:**
- `Layout.tsx` modificato per Report Editor: `p: 0`, `overflow: hidden`, `width: 100vw - drawerWidth`
- `ReportEditorPage.tsx`: `flex: 1`, `minHeight: 0` per espansione corretta
- Canvas container: `width: 100%` per occupare tutto lo spazio disponibile
- **FIX: Layout Report Designer Non Full-Width** - COMPLETATO
- **Problema:** Il report designer non occupava tutta la larghezza del browser
- **Causa:** Il Layout usava `width: 100%` invece di `100vw` e il padding non veniva rimosso per il report editor
- **Soluzione:**
- `Layout.tsx`: Usato `width: 100vw` e `calc(100vw - drawerWidth)` invece di `100%`
- `Layout.tsx`: Padding condizionale `p: 0` per route `/report-editor`
- `Layout.tsx`: `overflow: hidden` e `height: 100vh` per contenitore main
- `ReportEditorPage.tsx`: Rimossi margini negativi, usato `flex: 1` e `minHeight: 0`
- `EditorCanvas.tsx`: Modifiche utente per larghezza canvas
- **File modificati:** `Layout.tsx`, `ReportEditorPage.tsx`, `EditorCanvas.tsx`
- **NUOVA FEATURE: Panning e Zoom stile Draw.io nel Report Designer** - COMPLETATO (sessione precedente)
- **Problema:** Le scorciatoie da tastiera (Ctrl+X, Ctrl+C, etc.) venivano intercettate dal browser invece che dalla pagina
- **Soluzione:** Riscritto completamente l'handler delle scorciatoie con:
- Controllo se il focus è su campi input/textarea/contenteditable
- Nuovo metodo `isTextEditing()` esposto da EditorCanvasRef per verificare editing testo nel canvas
- `e.preventDefault()` per bloccare comportamento browser
- **Scorciatoie implementate:**
- `Ctrl+Z` - Annulla
- `Ctrl+Y` - Ripeti
- `Ctrl+S` - Salva
- `Ctrl+X` - Taglia
- `Ctrl+C` - Copia
- `Ctrl+V` - Incolla
- `Ctrl+D` - Duplica
- `Ctrl+A` - Seleziona tutto
- `Ctrl+L` - Blocca/Sblocca elemento
- `Ctrl+G` - Raggruppa
- `Ctrl+Shift+G` - Separa
- `Ctrl+]` - Porta avanti
- `Ctrl+Shift+]` - Porta in primo piano
- `Ctrl+[` - Porta indietro
- `Ctrl+Shift+[` - Porta in fondo
- `Delete/Backspace` - Elimina elemento
- `Escape` - Deseleziona
- **File modificati:**
- `EditorCanvas.tsx` - Aggiunto `isTextEditing()` a `EditorCanvasRef`
- `ReportEditorPage.tsx` - Importato `EditorCanvasRef`, aggiunto `canvasRef`, riscritto `useEffect` delle scorciatoie
- **FIX: Rimossa Toolbar Contestuale che causava Layout Shift** - COMPLETATO
- **Problema:** Quando si selezionava un oggetto nel canvas, appariva una toolbar aggiuntiva sotto quella principale che causava uno scroll della pagina
- **Soluzione:** Rimossa completamente la toolbar contestuale - le proprietà degli oggetti vengono gestite solo dal `PropertiesPanel` sulla destra
- **Rimosso da EditorToolbar.tsx:**
- Sezione "Contextual Toolbar Row" (desktop)
- Sezione "Contextual toolbar for text/shape" (tablet)
- Funzioni: `handleTextFormat()`, `handleTextAlign()`, `renderContextualToolbar()`
- Componente `ColorPickerButton`
- Costante `COLOR_PRESETS`
- Props: `selectedElement`, `onUpdateSelectedElement`
- Import non più usati: `TextField`, `ToggleButton`, `ToggleButtonGroup`, icone formattazione
- **File modificati:**
- `EditorToolbar.tsx` - Rimossa toolbar contestuale e codice correlato
- `ReportEditorPage.tsx` - Rimossi props `selectedElement` e `onUpdateSelectedElement` dalla chiamata a EditorToolbar
- **NUOVA FEATURE: Selezione Multipla nel Report Editor** - COMPLETATO
- Implementato sistema di selezione multipla personalizzato (senza usare ActiveSelection di Fabric.js che causava riposizionamento oggetti)
- **Selezione con rettangolo di trascinamento**: trascinando sul canvas vuoto appare rettangolo blu tratteggiato, al rilascio seleziona tutti gli oggetti che intersecano
- **Shift+click**: aggiunge/rimuove oggetti dalla selezione
- **Spostamento multiplo**: quando più oggetti sono selezionati, trascinandone uno si spostano tutti insieme
- **Feedback visivo**: oggetti selezionati mostrano bordo blu (#1976d2) e ombra
- **Gestione corretta degli eventi**: i ref (`selectedElementIdsRef`, `onSelectElementRef`, etc.) evitano stale closures negli event handler
- **File modificati:**
- `EditorCanvas.tsx` - Nuovi handler `handleMouseDown`, `handleMouseUp`, logica selezione multipla, refs per valori correnti
- `ReportEditorPage.tsx` - Cambiato `selectedElementId: string | null` → `selectedElementIds: string[]`, aggiornati tutti i riferimenti
**Lavoro completato nelle sessioni precedenti (28 Novembre 2025 notte):**
- **NUOVA FEATURE: Sincronizzazione Real-Time Efficiente** - COMPLETATO
- **Prima:** Al salvataggio veniva inviata solo una notifica `DataSaved`, l'altra sessione ricaricava il template dal server (lento)
- **Dopo:** Al salvataggio viene inviato l'intero template via SignalR (`BroadcastTemplateSync`), l'altra sessione lo applica direttamente (istantaneo)
- **Compressione automatica** per template > 10KB usando gzip via browser's CompressionStream API
- **Version tracking** per gestione conflitti (ignora template con versione più vecchia)
- Nuovo metodo Hub: `BroadcastTemplateSync(roomKey, templateJson, version, compressed)`
- Nuovo evento: `TemplateSync` con decompressione automatica lato client
- **FIX: Limite messaggio SignalR** - Aumentato `MaximumReceiveMessageSize` a 1MB in `Program.cs` (default era 32KB)
- **File modificati:**
- `CollaborationHub.cs` - Aggiunto `BroadcastTemplateSync` e `TemplateSyncMessage` con campo `Compressed`
- `collaboration.ts` - Aggiunto `broadcastTemplateSync()`, utilities compressione/decompressione (`compressString`, `decompressString`), handler `TemplateSync`
- `CollaborationContext.tsx` - Esposto `broadcastTemplateSync` e `onTemplateSync`
- `ReportEditorPage.tsx` - Sostituito `sendDataSaved()` con `broadcastTemplateSync()`, aggiunto handler per applicare template ricevuti
- `Program.cs` - Configurato SignalR con `MaximumReceiveMessageSize = 1MB`
- **FIX: Auto-Save Event-Based con Debounce** - COMPLETATO
- Riscritto auto-save per triggerare ad ogni modifica (non a intervalli)
- Debounce di 500ms per evitare salvataggi multipli durante editing rapido
- Usa `useRef` per `saveMutation`, `template`, `templateInfo` per evitare re-creazione del timeout
- Dipendenze effect: solo `autoSaveEnabled`, `isNew`, `hasUnsavedChanges`, `templateHistory.undoCount`
- Il check `isPending` avviene al momento dell'esecuzione del timeout, non come dipendenza
**Lavoro completato nelle sessioni precedenti (28 Novembre 2025 pomeriggio - sera):**
- **NUOVA FEATURE: Sistema Collaborazione Real-Time Globale** - COMPLETATO
- Migrato da sistema report-specific a sistema globale per tutta l'app
- `CollaborationHub.cs` - Hub SignalR generico per qualsiasi entità/pagina
- `collaboration.ts` - Service singleton per gestione connessione
- `CollaborationContext.tsx` - React Context con hooks (`useCollaboration`, `useCollaborationRoom`)
- `CollaborationIndicator.tsx` - Indicatore globale nella UI
- Room-based collaboration con formato `{entityType}:{entityId}`
- **FIX: Incompatibilità versione SignalR** - Rimosso package `Microsoft.AspNetCore.SignalR.Common` v10.0.0 incompatibile con .NET 9, downgrade client `@microsoft/signalr` a v8.0.7
- **FIX: Auto-save non funzionante** - Usati `useRef` per evitare re-run dell'effect causato da `saveMutation` nelle dependencies
**Lavoro completato nelle sessioni precedenti (28 Novembre 2025 tarda notte):**
- **NUOVA FEATURE: Toolbar Report Designer Migliorata Drasticamente** - COMPLETATO
- Design moderno stile Canva/Figma con gradient buttons e animazioni fluide
- **Sezioni etichettate** su desktop (INSERISCI, MODIFICA, CRONOLOGIA, VISTA, ZOOM, PAGINA)
- **Toolbar contestuale** dinamica che appare quando un elemento è selezionato:
- Per testo: formattazione (grassetto, corsivo, sottolineato), allineamento, color picker
- Per forme/linee: color picker riempimento/bordo, spessore bordo
- Per immagini: indicatore mantieni proporzioni
- Mostra tipo elemento, nome e dimensioni in tempo reale
- **Color Picker integrato** con palette di 20 colori predefiniti
- **Indicatore stato salvataggio** visivo: Salvato (verde), Non salvato (arancione), Salvataggio... (spinner)
- **Badge** sul pulsante Snap che mostra quante opzioni sono attive
- **Zoom esteso** fino al 300% con pulsante "Adatta alla finestra"
- Pannello scorciatoie tastiera ampliato
- Aggiunto `textDecoration` a `AprtStyle` per supportare sottolineato
- **FIX: Indicatore "Non Salvato" errato** - RISOLTO
- Prima usava `canUndo` che indicava solo presenza di history
- Ora usa `undoCount` confrontato con `lastSavedUndoCount` per tracking accurato
- **NUOVA FEATURE: Auto-Save con Toggle** - COMPLETATO
- Salvataggio automatico dopo 1 secondo di inattività (debounce)
- **Abilitato di default**
- Toggle nella toolbar (icona AutoMode) per attivare/disattivare
- Quando auto-save è attivo, il pulsante "Salva" manuale è nascosto
- Quando auto-save è disattivo, il pulsante "Salva" appare
- Non si attiva per template nuovi (richiede primo salvataggio manuale)
- Non si attiva durante salvataggio in corso
**Lavoro completato nelle sessioni precedenti (28 Novembre 2025 notte):**
- **NUOVA FEATURE: Responsive Design Completo** - COMPLETATO
- Tutta l'applicazione è ora responsive per mobile, tablet e desktop
- Breakpoints: mobile (<600px), tablet (600-900px), desktop (>900px)
- **Layout.tsx**: Sidebar collassata con icone su tablet, drawer mobile
- **ReportTemplatesPage**: Header stackato su mobile, FAB per nuovo template, dialog fullScreen
- **ReportEditorPage**: BottomNavigation + SwipeableDrawer (70vh) per pannelli su mobile, auto-zoom
- **EditorToolbar**: 3 varianti (mobile compatta con riga collassabile, tablet media, desktop completa)
- **Pannelli laterali** (DataBindingPanel, PropertiesPanel, PageNavigator): larghezza piena su mobile
- **DatasetSelector**: Header collassabile su mobile
- **PreviewDialog**: fullScreen su mobile con navigazione step-by-step (dataset → entity)
- **ImageUploadDialog**: fullScreen su mobile, area drag-drop ottimizzata, bottoni stacked
**Lavoro completato nelle sessioni precedenti (28 Novembre 2025 sera):**
- **FIX: Variabili Globali Report ({{$pageNumber}}, {{$totalPages}}, ecc.)** - RISOLTO
- Le variabili speciali ora vengono correttamente risolte nel PDF finale
- Aggiunta classe `PageContext` per passare numero pagina e totale pagine durante il rendering
- Propagato `PageContext` attraverso tutta la catena di rendering (bitmap, text, binding resolution)
- `ResolveBindingPath()` ora restituisce valori reali invece di placeholder
**Lavoro completato nelle sessioni precedenti (28 Novembre 2025):**
- **NUOVA FEATURE: Gestione Multi-Pagina nel Report Designer** - Completata
- Nuovo tipo `AprtPage` per definire pagine con impostazioni individuali (size, orientation, margins, backgroundColor)
- Ogni elemento ha `pageId` per assegnazione a pagina specifica
- Nuovo componente `PageNavigator.tsx` - sidebar con lista pagine, context menu, rinomina, duplica, elimina, riordina
- Navigazione rapida pagine in `EditorToolbar.tsx` (pulsanti prev/next, indicatore "X / Y")
- `PropertiesPanel.tsx` aggiornato per mostrare/modificare impostazioni pagina corrente
- Backend `ReportGeneratorService.cs` genera PDF multi-pagina correttamente
- Migrazione automatica template legacy (elementi senza pageId assegnati a prima pagina)
- **FIX CRITICO: Rotazione oggetti nel PDF** - Gli oggetti ruotati nel canvas ora vengono posizionati correttamente nel PDF generato
- Implementata la formula Fabric.js per calcolare il centro di rotazione
- Coordinate corrette per `originX='left'`, `originY='top'`
**Lavoro completato nelle sessioni precedenti:**
- Sistema Report PDF con editor visuale (98% completato)
- Fabric.js v6 canvas editor funzionante
- Multi-dataset support con preview
- **FIX: Data binding PDF ora funzionante** - I campi dati vengono risolti correttamente
- **FIX: Formattazione campi** - Date, valute, numeri formattati correttamente nel PDF
- Sistema Virtual Dataset implementato (CRUD completo)
- SignalR real-time updates funzionante
- **Context Menu ricco** - Tasto destro con opzioni complete stile Canva (copia, taglia, incolla, layer, allineamento, trasformazioni)
- **FIX: Posizionamento assoluto PDF FUNZIONANTE** - SVG con viewBox in mm, coordinate corrette
- **FIX: Immagini nel PDF** - Data URI, API URL e risorse embedded ora renderizzate correttamente
- **FIX: Font size nel PDF** - Conversione corretta da px screen a mm per SVG
**Per riprendere il lavoro sui Report:**
1. Vai alla sezione "Report PDF System - Implementation Details" più sotto
2. Consulta la "Checklist Completamento Report System" per vedere cosa manca
3. I file principali sono:
- Backend: `/src/Apollinare.API/Controllers/ReportsController.cs`
- Frontend: `/frontend/src/pages/ReportEditorPage.tsx`
- Canvas: `/frontend/src/components/reportEditor/EditorCanvas.tsx`
- **Context Menu:** `/frontend/src/components/reportEditor/ContextMenu.tsx`
- **PDF Generator:** `/src/Apollinare.API/Services/Reports/ReportGeneratorService.cs`
- **Page Navigator:** `/frontend/src/components/reportEditor/PageNavigator.tsx`
**Prossimi task prioritari:**
**MODULI BUSINESS (PRIORITÀ ALTA):**
1. [x] **Implementare modulo Magazzino (warehouse)** - COMPLETATO (backend)
- Backend: Entities, Service, Controllers, API completi
- Manca: Frontend (pagine React per gestione articoli, movimenti, giacenze)
2. [x] **Frontend modulo Magazzino** - Pagine React per warehouse (Articoli, Movimenti, Giacenze, Inventario)
3. [ ] **Implementare modulo Acquisti (purchases)** - Dipende da Magazzino
4. [ ] **Implementare modulo Vendite (sales)** - Dipende da Magazzino
5. [ ] **Implementare modulo Produzione (production)** - Dipende da Magazzino
6. [ ] **Implementare modulo Qualità (quality)** - Indipendente
**Report System (completamento):**
- [ ] Aggiungere rendering tabelle dinamiche per collection
- [ ] Gestire sezioni header/footer ripetute su ogni pagina
- [ ] UI per relazioni tra dataset multipli
**NOTA:** Vedere sezione "Prossimi Passi: Implementazione Moduli Business" per dettagli architetturali e principi di personalizzazione.
**Comandi utili (usa il Makefile!):**
```bash
# IMPORTANTE: Usa sempre il Makefile per compilare e avviare l'applicazione
make help # Mostra tutti i comandi disponibili
make install # Installa tutte le dipendenze (NuGet + npm)
make dev # Avvia backend e frontend in parallelo (dev mode)
make build # Compila tutto per produzione
make backend-run # Avvia solo backend (porta 5000)
make frontend-run # Avvia solo frontend (porta 5173)
make backend-watch # Backend con hot reload (dotnet watch)
make clean # Pulisce artefatti di build
make lint # Esegue ESLint sul frontend
make check # Verifica prerequisiti installati (dotnet, node, npm)
```
**IMPORTANTE:** Dopo modifiche al codice, i servizi backend e frontend vanno **sempre riavviati** per vedere le modifiche:
- Backend: fermare con `Ctrl+C` e rilanciare `make backend-run`
- Frontend: in dev mode (`make frontend-run`) il hot-reload è automatico per la maggior parte delle modifiche, ma per modifiche strutturali (nuovi file, cambi a tipi, etc.) potrebbe essere necessario riavviare
---
## Project Overview
This repository contains documentation for migrating the **Apollinare Catering & Banqueting Management Software** from Oracle APEX to .NET + React TypeScript.
**Original Application:**
- Oracle APEX 21.1.0 (Application ID: 112)
- 56 pages, 302 items, 98 processes
- Database: Oracle 18 XE (schema: APOLLINARECATERINGPROD)
- Language: Italian
**Target Stack:**
- Backend: .NET (C#)
- Frontend: React TypeScript (not Vue - note the user request mentions Vue but the actual target is React TypeScript)
- Database: Oracle 18 XE (read-only access for analysis)
## Database Connection (Read-Only)
**Connection Details:**
- Database: Oracle 18 XE
- Username: `apollinarecateringprod`
- Password: `bmwmRaSBRT53Z2J8CCvYK45EPDyAJ4`
- Database: `xepdb1`
- Hostname: `apollinare`
- Port: `1521`
**Important:** This connection is READ-ONLY. Use it only to analyze schema, extract business logic from procedures/packages/functions, and understand data relationships.
## Application Architecture
### Core Business Domain: Event Catering Management
The application manages the complete lifecycle of catering events from quote to execution, including:
- Event creation and management
- Client and location management
- Inventory (articles) with image storage
- Quote generation with complex calculations
- Resource (staff) scheduling
- Kitchen and setup reports
- Multi-level authorization system
### Main Business Entities
**Events (EVENTI)** - Central entity
- Event details (date, location, client, event type)
- Guest counts by type (adults, children, seated, buffet)
- Status workflow: 0 (Scheda) → 10 (Preventivo/Quote) → 20 (Confermato/Confirmed)
- Quote expiration tracking
- Distance calculations for location
**Event Details (1:N relationships):**
- `EVENTI_DET_OSPITI` - Guest type breakdown
- `EVENTI_DET_PREL` - Pick lists (articles needed for the event)
- `EVENTI_DET_RIS` - Resource assignments (staff)
- `EVENTI_DET_DEGUST` - Tasting event details
- `EVENTI_ACCONTI` - Deposits/advances
- `EVENTI_ALLEG` - Attachments
- `EVENTI_ALTRICOSTI` - Other costs
**Master Data:**
- `ARTICOLI` - Articles/items with images (BLOB), quantities, coefficients
- `TB_CODICI_CATEG` - Categories with calculation coefficients (COEFF_A/B/S)
- `TB_TIPI_MAT` - Material types
- `TB_TIPI_EVENTO` - Event types with meal classifications
- `TB_TIPI_OSPITI` - Guest types
- `CLIENTI` - Clients
- `LOCATION` - Event locations
- `RISORSE` - Resources (staff) with type classification
### Critical Business Logic in Database
**Key Stored Procedures:**
- `EVENTI_AGGIORNA_QTA_LISTA(p_event_id)` - Updates pick list quantities based on guest counts and coefficients
- `EVENTI_AGGIORNA_TOT_OSPITI(p_event_id)` - Recalculates total guest count
- `EVENTI_RICALCOLA_ACCONTI(p_event_id)` - Recalculates deposit amounts
- `EVENTI_COPIA` - Event duplication functionality
- `EVENTI_PREPARE` - Event preparation process
**Key Functions:**
- `F_GET_QTA_IMPEGNATA(cod_articolo, data)` - Returns committed quantity for an article on a specific date (inventory reservation)
- `F_EVENTO_SCADUTO(data_scad, stato, ...)` - Checks if event quote has expired
- `F_MAX_NUMERO_EVENTI_RAGGIUNTO(data)` - Enforces daily event limit
- `F_USER_IN_ROLE(app_user, role)` - Role-based authorization
- `STRING_TO_TABLE_ENUM(string, position, delimiter)` - Utility for string parsing
**Important Views:**
- `V_IMPEGNI_ARTICOLI` - Calculates article commitments across events (inventory availability)
- `V_IMPEGNI_ARTICOLI_LOC` - Article commitments by location
- `VW_CALENDARIO_EVENTI` - Calendar view of events
### Quantity Calculation Algorithm
The application uses a sophisticated coefficient-based system:
1. **Coefficients** are defined at category level (`TB_CODICI_CATEG.COEFF_A/B/S`)
2. **Standard quantities** are stored per article (`ARTICOLI.QTA_STD_A/S/B`)
3. **Guest counts** by type determine multipliers (`EVENTI_DET_OSPITI`)
4. **Final quantities** calculated as: `Guest_Count × Coefficient × Standard_Qty`
Types: A (Adulti/Adults), S (Seduti/Seated), B (Buffet)
### Authorization Model
**5 Authorization Levels:**
1. **Admin_auth_schema** - Full admin access
- Users: admin, monia, andrea, maria, sabrina, nicole, cucina, developer, elia.ballarani
2. **User Read/Write** - Controlled by `USERS_READONLY` table
- `FLGWRITE` flag determines write access
3. **Consuntivi** - Access to financial summaries
- Users from `GET_CONSUNTIVI_USERS` view
4. **Gestori** (Managers) - Manager-level permissions
- Users from `GET_GESTORI_USERS` view
5. **Solo Admins** - Highest level
- Only: admin, monia
**Session Management:**
- `SET_USER_READONLY` process runs before header on every page
- Sets `APP_READ_ONLY` application item based on user permissions
### Page Structure (56 Pages)
**Master Data Pages:**
- Pages 2-3: Articles (list + form)
- Pages 4-5: Categories
- Pages 6-7: Types
- Pages 17-18: Clients
- Pages 15, 20: Locations
- Page 31: Resources (staff)
**Event Management:**
- Page 1: Dashboard
- Page 8: Event creation wizard
- Page 9: Event list
- Page 12: Calendar view
- Pages 13-14: Event types
- **Page 22: Main event form** (most complex - multiple interactive grids)
- Page 27, 32: Tastings
- Page 35: Event cards/confirmed cards
- Page 48: Event templates
**Reports:**
- Page 16: Grid view
- Page 25: Kitchen summary
- Page 28: Cakes and extra costs
- Page 30: Setup summary
- Page 38: Resources summary
- Page 39: Article commitments
**Admin:**
- Page 45: Data management
- Page 46: Max events configuration
- Page 47: Permissions
- Page 49: Scheduled jobs
- Page 50: Sent emails
- Page 51: Pending emails
### External Integrations
**JasperReports:**
- Quote reports (preventivi)
- Event cards (schede evento)
- Kitchen summaries
- Custom iframeObj.js wrapper for embedding reports
**Email System:**
- Mail queue (pages 50-51)
- Background job processing (page 49)
- Template-based notifications
**Custom JavaScript:**
- `ajaxUtils.js` - AJAX utilities for dynamic updates
- `notifica(pText, pType)` - Dynamic notifications
- `setSessionState(elemList, pCallback)` - Session state management
- `ajaxExec(...)` - Generic AJAX execution
- `execProcessAsync(...)` - Async process execution
- `execQueryAsync(...)` - Async query execution
### Migration Considerations
**Complex Features Requiring Special Attention:**
1. **Page 22 (Nuovo Evento)** - Most complex page
- Multiple editable interactive grids on single page
- Master-detail relationships with real-time calculations
- Guest type grid → triggers quantity recalculations in pick list grids
- Resource assignment grid
- Requires careful state management in React
2. **BLOB Storage for Images**
- Article images stored as BLOBs in Oracle
- Migration strategy needed (Azure Blob Storage, AWS S3, or filesystem)
- MIMETYPE tracking for proper rendering
3. **PL/SQL Business Logic**
- Decision needed: Port to C# or keep as Oracle functions?
- Quantity calculations are complex - ensure parity
- Inventory commitment logic (V_IMPEGNI_ARTICOLI) is critical
4. **State Management**
- Heavy use of APEX session state
- Consider Redux Toolkit or Zustand for React
- Real-time grid updates and calculations
5. **Reporting**
- JasperReports replacement needed
- Options: SSRS, Crystal Reports, DevExpress, or PDF libraries (iTextSharp, QuestPDF)
6. **Email Queue System**
- Asynchronous processing required
- Consider: Hangfire, Azure Functions, or background services
7. **Calendar Component**
- Page 12 uses APEX calendar
- React options: FullCalendar, React Big Calendar, @event-calendar/core
8. **Multi-Grid Interactions**
- Interactive grids with master-detail relationships
- Consider: AG Grid, DevExtreme DataGrid, or Material-UI DataGrid
## Business Rules to Preserve
1. **Event Status Workflow:** Must follow 0 → 10 → 20 progression
2. **Quote Expiration:** Automatic status change when `DATA_SCAD_PREVENTIVO` passed
3. **Max Events Per Day:** Enforced limit (configurable)
4. **Article Commitment Tracking:** Prevent overbooking of inventory
5. **Coefficient-Based Calculations:** Ensure quantity formulas match exactly
6. **Deposit Calculations:** Auto-recalculation on cost changes
7. **Role-Based Access:** 5-level authorization system
8. **Read-Only Mode:** User-specific write restrictions
## Data Extraction Queries
When analyzing the database, useful queries:
```sql
-- Get all tables in schema
SELECT table_name FROM user_tables ORDER BY table_name;
-- Get table structure
SELECT column_name, data_type, nullable, data_default
FROM user_tab_columns
WHERE table_name = 'EVENTI'
ORDER BY column_id;
-- Get all procedures and functions
SELECT object_name, object_type
FROM user_objects
WHERE object_type IN ('PROCEDURE', 'FUNCTION', 'PACKAGE')
ORDER BY object_type, object_name;
-- Get procedure source
SELECT text FROM user_source
WHERE name = 'EVENTI_AGGIORNA_QTA_LISTA'
ORDER BY line;
-- Get view definitions
SELECT view_name, text FROM user_views
WHERE view_name LIKE 'V_%' OR view_name LIKE 'VW_%';
-- Get foreign key relationships
SELECT a.constraint_name, a.table_name, a.column_name,
c_pk.table_name r_table_name, c_pk.constraint_name r_constraint_name
FROM user_cons_columns a
JOIN user_constraints c ON a.constraint_name = c.constraint_name
JOIN user_constraints c_pk ON c.r_constraint_name = c_pk.constraint_name
WHERE c.constraint_type = 'R'
ORDER BY a.table_name, a.constraint_name;
```
## File References
- `apollinare-db-connection.md` - Database connection details (credentials)
- `f112.sql` - Complete APEX export (53,282 lines)
- Application structure
- Page definitions
- Processes and validations
- LOVs and static data
- JavaScript libraries
## Development Approach
When working on migration tasks:
1. **Always query the database** to understand current data structure and relationships
2. **Extract PL/SQL source code** for procedures/functions before implementing equivalent C# logic
3. **Document business rules** discovered in stored procedures
4. **Preserve Italian field names** in database but consider English in application layer
5. **Test quantity calculations** thoroughly - they are core to the business
6. **Map APEX page flows** to React routes and components
7. **Identify reusable components** (grids, forms, lookups)
8. **Plan data migration** for BLOBs and complex relationships
## Key Terminology (Italian → English)
- **Scheda** → Card/Draft (Event status 0)
- **Preventivo** → Quote (Event status 10)
- **Confermato** → Confirmed (Event status 20)
- **Lista Prelievo** → Pick List (articles for event)
- **Articoli** → Articles/Items
- **Ospiti** → Guests
- **Risorse** → Resources (staff)
- **Degustazioni** → Tastings
- **Allestimenti** → Setups
- **Acconti** → Deposits/Advances
- **Impegni** → Commitments (inventory reservations)
## Notes
- The application is mature and in production use
- Italian language throughout (UI, database, code comments)
- Complex business logic embedded in database layer
- Heavy use of APEX-specific features (Interactive Grids, Dynamic Actions)
- Real-time calculations and validations are critical to user experience
---
## Report PDF System - Implementation Details
### Overview
Sistema completo di generazione report PDF con editor visuale drag-and-drop (stile Canva) e metalinguaggio APRT (Apollinare Report Template) per template portabili.
### Stack Tecnologico
**Backend:**
- QuestPDF (Community License) - Generazione PDF programmatica
- .NET 9 Web API con Entity Framework Core
- SQLite per storage template, font e immagini
**Frontend:**
- React 19 + TypeScript + Vite
- Fabric.js v6 - Canvas editor per design visuale
- Material-UI per componenti UI
### Stato Corrente dell'Implementazione
#### Backend (COMPLETATO)
**Entities** (`/src/Apollinare.Domain/Entities/`):
- `ReportTemplate.cs` - Template con JSON, thumbnail, metadata
- `ReportFont.cs` - Font custom uploadabili (TTF/OTF)
- `ReportImage.cs` - Immagini riutilizzabili nei report
**Services** (`/src/Apollinare.API/Services/Reports/`):
- `ReportGeneratorService.cs` - Parsing APRT e generazione PDF con QuestPDF
- `AprtModels.cs` - Modelli C# per il metalinguaggio APRT
**Controllers** (`/src/Apollinare.API/Controllers/`):
- `ReportTemplatesController.cs` - CRUD template, clone, import/export
- `ReportResourcesController.cs` - Gestione font e immagini
- `ReportsController.cs` - Generazione PDF, schema dati, dataset management
**API Endpoints disponibili:**
```
# Templates
GET /api/report-templates
GET /api/report-templates/{id}
POST /api/report-templates
PUT /api/report-templates/{id}
DELETE /api/report-templates/{id}
POST /api/report-templates/{id}/clone
GET /api/report-templates/{id}/export
POST /api/report-templates/import
GET /api/report-templates/categories
# Resources
GET /api/report-resources/fonts
POST /api/report-resources/fonts
DELETE /api/report-resources/fonts/{id}
GET /api/report-resources/fonts/families
GET /api/report-resources/images
POST /api/report-resources/images
DELETE /api/report-resources/images/{id}
# Report Generation
POST /api/reports/generate
GET /api/reports/evento/{eventoId}
POST /api/reports/preview
GET /api/reports/datasets
GET /api/reports/schema/{datasetId}
GET /api/reports/datasets/{datasetId}/entities
```
#### Frontend (COMPLETATO ~90%)
**Pagine** (`/frontend/src/pages/`):
- `ReportTemplatesPage.tsx` - Lista template con cards, filtri, import/export
- `ReportEditorPage.tsx` - Editor principale con undo/redo, shortcuts
**Componenti Editor** (`/frontend/src/components/reportEditor/`):
- `EditorCanvas.tsx` - Canvas Fabric.js per design visuale
- `EditorToolbar.tsx` - Toolbar con strumenti, zoom, grid, azioni
- `PropertiesPanel.tsx` - Pannello proprietà elemento/pagina
- `DataBindingPanel.tsx` - Browser campi dati con supporto multi-dataset
- `DatasetSelector.tsx` - Selezione dataset per template
- `PreviewDialog.tsx` - Dialog selezione entità per anteprima
**Types** (`/frontend/src/types/report.ts`):
- Definizioni complete APRT (AprtTemplate, AprtElement, AprtStyle, etc.)
- DTOs per API (ReportTemplateDto, DataSchemaDto, DatasetTypeDto, etc.)
- Utility functions (mmToPx, pxToMm, getPageDimensions)
**Services** (`/frontend/src/services/reportService.ts`):
- reportTemplateService - CRUD template
- reportFontService - Gestione font
- reportImageService - Gestione immagini
- reportGeneratorService - Generazione PDF e schema
### Metalinguaggio APRT (Apollinare Report Template)
Formato JSON esportabile/importabile per portabilità template:
```json
{
"version": "1.0",
"meta": {
"name": "Template Evento",
"pageSize": "A4",
"orientation": "portrait",
"margins": { "top": 20, "right": 15, "bottom": 20, "left": 15 }
},
"resources": {
"fonts": [],
"images": []
},
"dataSources": {
"evento": { "type": "object", "schema": "evento" }
},
"sections": [],
"elements": [
{
"id": "uuid",
"type": "text",
"position": { "x": 20, "y": 20, "width": 100, "height": 20 },
"style": {
"fontFamily": "Helvetica",
"fontSize": 14,
"color": "#000000"
},
"content": { "type": "binding", "expression": "{{evento.codice}}" },
"section": "body"
}
]
}
```
**Tipi elemento supportati:** text, image, shape, table, line, barcode
**Data binding:** `{{campo}}`, `{{dataset.campo}}`, `{{collection.campo}}`
**Variabili speciali:** `{{$pageNumber}}`, `{{$totalPages}}`, `{{$date}}`, `{{$datetime}}`
### Dataset Disponibili
| Dataset ID | Nome | Descrizione |
| ---------- | -------- | ------------------------------------------------------------------ |
| evento | Evento | Dati evento con cliente, location, dettagli ospiti, costi, risorse |
| cliente | Cliente | Anagrafica clienti completa |
| location | Location | Sedi e location eventi |
| articolo | Articolo | Catalogo articoli e materiali |
| risorsa | Risorsa | Staff e personale |
### Funzionalità Implementate
- [x] Editor visuale drag-and-drop con Fabric.js
- [x] Supporto elementi: testo, forme, linee, tabelle, immagini (placeholder)
- [x] Gestione zoom (25% - 300%)
- [x] Griglia e snap to grid
- [x] Undo/Redo (max 100 stati)
- [x] Shortcuts tastiera (Ctrl+Z, Ctrl+Y, Ctrl+S, Delete)
- [x] Pannello proprietà con posizione, stile, contenuto
- [x] Data binding con browser campi disponibili
- [x] Selezione multipla dataset per template
- [x] Preview con selezione entità reali
- [x] Salvataggio/caricamento template
- [x] Import/export template come file .aprt
- [x] Clone template
- [x] Generazione PDF default per eventi
- [x] Formattazione campi (valuta, data, numero, percentuale)
- [x] **Responsive design completo** (mobile, tablet, desktop)
- [x] **Toolbar professionale** stile Canva/Figma con sezioni etichettate
- [x] **Toolbar contestuale** per formattazione rapida (testo, forme, immagini)
- [x] **Color picker integrato** con palette preset
- [x] **Auto-save** con toggle (abilitato di default, 1s debounce)
- [x] **Indicatore stato salvataggio** accurato (Salvato/Non salvato/Salvataggio...)
### Cosa Manca per Completare
#### Alta Priorità
- [ ] **Caricamento immagini reali** - Attualmente placeholder, implementare upload e rendering
- [ ] **Tabelle dinamiche** - Rendering collection dati (es. lista ospiti, articoli)
- [ ] **Sezioni header/footer** - Ripetizione su ogni pagina
- [ ] **Font custom** - Upload e utilizzo font TTF/OTF nei PDF
#### Media Priorità
- [ ] **Relazioni tra dataset** - UI per collegare campi tra dataset diversi
- [ ] **Barcode/QRCode** - Supporto codici a barre
- [ ] **Formule calcolate** - Espressioni matematiche nei campi
- [ ] **Stili condizionali** - Formattazione basata su valore dati
- [ ] **Raggruppamento elementi** - Group/ungroup nel canvas
#### Bassa Priorità
- [ ] **Template predefiniti** - Library di template pronti all'uso
- [ ] **Anteprima live** - Preview in tempo reale durante editing
- [x] ~~**Multi-pagina** - Editor pagine multiple~~ - COMPLETATO
- [ ] **Righelli e guide** - Ausili allineamento avanzati
- [ ] **Esportazione altri formati** - Excel, Word oltre PDF
---
## Checklist Completamento Report System
### Backend
- [x] Entity ReportTemplate
- [x] Entity ReportFont
- [x] Entity ReportImage
- [x] ReportTemplatesController (CRUD + clone + import/export)
- [x] ReportResourcesController (fonts + images)
- [x] ReportsController (generate + preview + schema + datasets)
- [x] ReportGeneratorService con QuestPDF
- [x] Schema dati per tutti i dataset (evento, cliente, location, articolo, risorsa)
- [x] Generazione PDF default evento
- [x] Generazione PDF multi-pagina
- [ ] Rendering tabelle dinamiche da collection
- [ ] Supporto font custom nel PDF
- [ ] Rendering immagini da storage
### Frontend
- [x] ReportTemplatesPage (lista + filtri + azioni)
- [x] ReportEditorPage (editor principale)
- [x] EditorCanvas con Fabric.js v6
- [x] EditorToolbar completa
- [x] PropertiesPanel (posizione + stile + contenuto)
- [x] DataBindingPanel multi-dataset
- [x] DatasetSelector
- [x] PreviewDialog con selezione entità
- [x] Types APRT completi
- [x] Services API completi
- [x] Undo/Redo
- [x] Keyboard shortcuts
- [x] PageNavigator (gestione multi-pagina)
- [x] Navigazione pagine in toolbar
- [x] **Responsive design** (mobile/tablet/desktop)
- [ ] Upload e gestione immagini nell'editor
- [ ] Editor tabelle avanzato (colonne, binding dati)
- [ ] UI relazioni tra dataset
- [ ] Gestione sezioni header/footer
### Testing
- [x] Build frontend senza errori
- [x] Build backend senza errori
- [ ] Test funzionale editor canvas
- [x] Test generazione PDF con dati reali (binding e formattazione funzionanti)
- [ ] Test import/export template
- [ ] Test con font e immagini custom
### Documentazione
- [x] Documentazione APRT metalanguage
- [x] Lista API endpoints
- [x] Checklist implementazione
- [ ] Guida utente editor
- [ ] Esempi template comuni
---
## Note Tecniche per Future Sessioni
### Struttura File Report System
```
src/
├── Apollinare.Domain/Entities/
│ ├── ReportTemplate.cs # Entity template con TemplateJson
│ ├── ReportFont.cs # Font custom uploadati
│ └── ReportImage.cs # Immagini riutilizzabili
│
├── Apollinare.API/
│ ├── Controllers/
│ │ ├── ReportTemplatesController.cs # CRUD template
│ │ ├── ReportResourcesController.cs # Font e immagini
│ │ └── ReportsController.cs # Generazione PDF + schema
│ │
│ └── Services/Reports/
│ ├── ReportGeneratorService.cs # QuestPDF generator
│ └── AprtModels.cs # Modelli C# per APRT JSON
frontend/src/
├── pages/
│ ├── ReportTemplatesPage.tsx # Lista template
│ └── ReportEditorPage.tsx # Editor principale
│
├── components/reportEditor/
│ ├── EditorCanvas.tsx # Fabric.js canvas
│ ├── EditorToolbar.tsx # Toolbar strumenti
│ ├── PropertiesPanel.tsx # Proprietà elemento
│ ├── DataBindingPanel.tsx # Browser campi dati
│ ├── DatasetSelector.tsx # Selezione dataset
│ ├── PreviewDialog.tsx # Dialog anteprima
│ └── ContextMenu.tsx # Menu tasto destro (NEW)
│
├── types/
│ └── report.ts # Types APRT + DTOs
│
└── services/
└── reportService.ts # API calls
```
### Problemi Risolti (da ricordare)
1. **Fabric.js v6 breaking changes:**
- `sendToBack()` → `canvas.sendObjectToBack(obj)`
- Event handlers hanno signature diversa
- Proprietà `data` non è nel tipo base, serve cast a `FabricObjectWithData`
2. **TypeScript strict mode:**
- Usare `as any` per event handlers Fabric.js
- Interface `FabricObjectWithData` per oggetti con metadata custom
3. **QuestPDF TimeSpan:**
- `evento.OraInizio` è `TimeSpan?` non `string`
- Formattare con `{evento.OraInizio:hh\\:mm}`
4. **Data Binding PDF (FIX 27/11/2025):**
- **Problema:** I binding `{{dataEvento}}` non venivano risolti - PDF mostrava campi vuoti
- **Causa:** Il frontend creava binding senza prefisso dataset quando c'era un solo dataset
- **Soluzione Frontend** (`DataBindingPanel.tsx`): Sempre includere il prefisso dataset
```typescript
// Prima: {{dataEvento}} - non funzionava
// Dopo: {{evento.dataEvento}} - corretto
const createBinding = (datasetId: string, fieldName: string) => {
return `{{${datasetId}.${fieldName}}}`;
};
```
- **Soluzione Backend** (`ReportGeneratorService.cs`): Aggiunto fallback per compatibilità con template esistenti
```csharp
// Se binding senza prefisso, cerca in tutti i dataset
if (current == null && parts.Length == 1)
{
foreach (var kvp in dataContext)
{
var foundValue = GetPropertyValue(kvp.Value, path);
if (foundValue != null) { current = foundValue; break; }
}
}
```
- **Formattazione:** Aggiunto `ResolveBindingWithFormat()` per applicare format (date, currency, etc.)
5. **SignalR Connection (FIX 27/11/2025):**
- Aggiunto `app.UseWebSockets()` in Program.cs prima di `app.UseRouting()`
- Configurato signalr.ts con `withAutomaticReconnect()`
6. **MUI Fragment in Menu (FIX 27/11/2025):**
- Menu component non accetta Fragment come child
- Sostituire `<>...>` con array `[
`
- Fix: `