Compila RAS v2 - Gap analysis gestione foto¶
Data: 2026-07-31
Spec di riferimento: docs/operativo/ras_compila_v2_photo_spec_20260731.md
Sintesi¶
La gestione foto attuale funziona per casi semplici, ma non ha ancora un modello unico.
La stessa foto puo comparire in:
payload.images;payload.detail.image;payload.detail.images;payload.detail.gallery.items;payload.detail.libretto.images;payload.interventi[].immagini;PACK.photo_tray;- IndexedDB locale come
local:<id>; - draft server
legacy_dynamic_draft; - answer server
legacy_dynamic_answer; - output stampa.
Questo rende instabili upload, cancellazione, refresh, duplicati e stampa, perche ogni funzione deve ricordarsi di aggiornare molte strutture.
Stato attuale rispetto alla spec¶
1. Foto subito visibili¶
Parzialmente presente.
Il client crea riferimenti local:<id> e usa IndexedDB/blob URL per mostrare subito le immagini. Questo e corretto come direzione.
Gap:
- la visibilita dipende dal fatto che il blob locale sia ancora presente in IndexedDB;
- non esiste un registro foto separato che dica "questa foto esiste, e locale/pending/server";
- l'upload puo sostituire chiavi in molte strutture con
replaceLocalKeyEverywhere(), ma il modello resta fragile.
2. Foto visibili dopo refresh¶
Parzialmente presente.
Esistono funzioni per:
- recuperare
local:<id>da IndexedDB; - diagnosticare foto locali/orfane;
- mostrare stato foto locali.
Gap:
- la fonte dati resta il payload domanda, non un ledger;
- se un riferimento locale resta ma il blob manca, serve UI piu centrale e meno "debug";
- la ricostruzione da draft/server puo sovrascrivere o fondere stati locali in modo difficile da prevedere.
3. Cancellazione¶
Non conforme alla spec.
Stato attuale:
savePhotoDeletionOnline()richiede online per cancellazioni server;- se la foto e
local:la rimuove localmente e puo cancellare il blob IndexedDB; - non esiste un cestino RAS;
- non esiste una coda
delete_pendingvera; deleteImageKeyEverywhere()rimuove globalmente una chiave da tutte le risposte e dal parcheggio.
Gap critico:
- cancellare non deve distruggere senza recupero;
- offline delete deve essere registrato e sincronizzato dopo;
- serve distinguere "rimuovi assegnazione dalla domanda" da "elimina asset".
4. Parcheggio¶
Presente e importante.
Stato attuale:
PACK.photo_trayesiste;- UI
openTrayModal()esiste; - le foto possono essere aggiunte/rimosse dal parcheggio.
Gap:
- parcheggio e solo lista chiavi, senza metadati;
- manca origine domanda/sezione;
- non e collegato a un ledger;
- non e distinto formalmente dal futuro cestino.
5. Duplicati¶
Parzialmente corretto dopo fix recenti.
Stato attuale:
removeOneImageRefFromPayload()rimuove una singola occorrenza usando indice ogalleryItemId;- questo migliora il caso "cancello una tessera e ne spariscono due".
Gap:
- esistono ancora funzioni globali che rimuovono tutte le occorrenze della stessa chiave;
- manca il concetto di
assignment_idstabile per ogni tessera; - stessa foto in piu domande e duplicato nella stessa domanda non sono modellati esplicitamente.
6. Stampa/PDF¶
Non conforme alla spec.
Stato attuale:
_rasV2ImmediatePrintBlockReason()blocca stampa se ci sono foto locali o pending;_rasEnsureV2ConsolidatedForPrint()prova a consolidare e poi blocca se restanolocal:;- i pulsanti stampa vengono disabilitati quando c'e blocco.
Gap critico:
- la stampa tecnica deve essere sempre consentita;
- foto locali/pending devono diventare immagini se disponibili nel browser, oppure placeholder;
- non deve esserci blocco totale solo per pending/local.
7. Offline¶
Parzialmente presente ma non completo.
Stato attuale:
- IndexedDB salva blob locali;
- esistono queue/draft/sync state;
- upload pending e retry sono parzialmente implementati;
- ci sono diagnostiche locali.
Gap:
- non esiste coda operazioni foto completa;
- mancano
delete_pending,restore_pending,move_pending,park_pending,trash_pending; - non esiste una tabella/struttura server di reconciliation per operazioni foto;
- conflitti e cancellazioni offline non sono modellati come eventi.
Problema architetturale¶
Il codice attuale lavora per "chiave immagine" dentro payload domanda.
La spec richiede invece tre livelli:
- asset foto;
- assegnazione foto a domanda/parcheggio/cestino;
- operazione pending/offline.
Senza questa separazione, ogni fix tende a moltiplicare condizioni speciali.
Proposta di refactor¶
Fase 1 - Stabilizzazione modello client¶
Senza cambiare ancora DB:
- introdurre una struttura
PACK.photo_ledger; - ogni foto ha
asset_id,key,local_id,status,created_at,origin; - ogni tessera ha
assignment_id,asset_id,scope,question_id,section_code,state; - parcheggio e cestino diventano viste/assegnazioni del ledger;
- mantenere compatibilita scrivendo ancora
imagesedetail.gallery.itemsper stampa/export.
Obiettivo: togliere la logica foto dalle singole funzioni UI e centralizzarla.
Fase 2 - Coda operazioni offline¶
Introdurre nel client una photo_ops_queue persistita in IndexedDB/draft:
- upload;
- delete assignment;
- restore assignment;
- move assignment;
- park;
- trash.
Ogni operazione deve essere idempotente con un op_id.
Fase 3 - API server leggere¶
Possibile evoluzione server:
- endpoint per applicare operazioni foto;
- endpoint per leggere ledger/cestino;
- tabella o JSON nel draft per ledger pilota;
- solo dopo stabilita, eventuale normalizzazione DB.
Fase 4 - Stampa tecnica permissiva¶
Cambiare la logica stampa:
- non bloccare con foto locali/pending;
- generare sempre preview/PDF tecnico;
- usare immagini disponibili;
- usare placeholder per immagini non risolvibili;
- lasciare warning in UI e nel PDF.
Ordine consigliato¶
- Introdurre
photo_ledgerclient-only con compatibilita verso payload attuale. - Migrare aggiunta/cancellazione/parcheggio a funzioni ledger.
- Aggiungere cestino RAS client/draft.
- Aggiungere coda operazioni offline per cancellazione/spostamento/ripristino.
- Rendere stampa v2 permissiva.
- Solo dopo, valutare endpoint/server ledger.
Rischi¶
- Refactor troppo grande in un colpo solo rischia regressioni su upload e stampa.
- Tenere doppio modello temporaneo, ledger + payload legacy, richiede test mirati.
- La stampa server non puo vedere blob locali del browser: serve placeholder o un flusso preview locale se si vogliono includere immagini non uploadate.
- Se si elimina fisicamente un blob server prima di verificare tutte le assegnazioni, si rischia perdita dati.
Test minimi da creare¶
- creazione ledger da payload legacy;
- aggiunta foto locale crea asset + assignment + payload compatibile;
- upload riuscito aggiorna asset senza perdere assignment;
- cancellazione sposta assignment a cestino;
- cancellazione offline crea op pending;
- ripristino da cestino torna alla domanda originale;
- parcheggio mantiene asset e cambia assignment;
- duplicato stessa domanda cancella una sola assignment;
- stessa foto in due domande cancella una sola assignment;
- stampa non bloccata con foto locali/pending.