# Gestire uno storico di modifiche ai record del database con Foundation

**URL:** <https://community.instantdeveloper.com/t/gestire-uno-storico-di-modifiche-ai-record-del-database-con-foundation/795>\
**Category:** Progetti di esempio Foundation\
**Tags:** esempi, idf\
**Created:** [5 Settembre 2025, 6:00am UTC](https://community.instantdeveloper.com/t/gestire-uno-storico-di-modifiche-ai-record-del-database-con-foundation/795 "2025-09-05T06:00:09Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![paolo.giannelli](https://community.instantdeveloper.com/user_avatar/community.instantdeveloper.com/paolo.giannelli/32/12_2.png) [@paolo.giannelli](https://community.instantdeveloper.com/u/paolo.giannelli)\
**Post date:** [5 Settembre 2025, 6:00am UTC](https://community.instantdeveloper.com/t/gestire-uno-storico-di-modifiche-ai-record-del-database-con-foundation/795/1 "2025-09-05T06:00:09Z")

</div>

Ho realizzato un progetto di esempio per **Instant Developer Foundation** che implementa sul mitico database _Northwind_ una gestione generalizzata di salvataggio delle modifiche della versione precedente del record o della catena di record in caso di master-detail.

L’esempio lo potete scaricare qui: [Log Modifiche Documenti.zip](https://community.instantdeveloper.com/uploads/short-url/cLrgM9MXT6ejHrwYPadfefp4W81.zip) (1,4 MB)

Naturalmente questa cosa è _facilmente_ 😂 realizzabile utilizzando i documenti di Instant Developer Foundation, gli eventi globali e alcune caratteristiche del framework.

### Vi racconto un po’ come funziona.

Per prima cosa occorre avere un posto dove memorizzare le versioni precedenti un aggiornamento di record di una tabella e nel database _Northwind_ ho creato la tabella Logs con i seguenti campi:

- ID - la chiave primaria
- Document - Nome del documento
- Date Mod - Data e ora fino alla quale il documento aveva la forma qui ssalvata
- Doc DNA - La chiave univoca del documento
- Record - qui salviamo in formato JSON il documento prima della modifica

Al salvataggio dei documenti andremo a scrivere in questa tabella la versione prima della modifica e lo facciamo utilizzando l’vento _GlobalBeforeSave_ dei documenti.  
Il codice nell’evento utilizza la reflection di Instant Developer Foundation per analizzare la struttura del documento ed andare a prendersi i valori precedenti dei campi e richiamare il metodo CreaLog().

Le strutture padre-figlio scrivono un unico record sulla tabella Logs con tutto il documento comprensivo dei due livelli come si vede nel codice qui sotto (_occorre modificarlo per renderlo multilivello_).

```auto
// Se sono in modifica e non sto salvado un documento di classe Log procedo
if (Phase == 2 && Doc.updated && Doc.typeName() != "Log")
{
  // Disabilito il log singolo dei documenti figli di una struttura padre figlio (viene fatto nel documento principale)
  IDDocumentStructure ds = Doc.getStructure()
   
  for (int i = 1; i <= ds.getCollectionCount(); i = i + 1)
  {
    IDCollection coll of IDDocument = (IDCollection)Doc.getCollection(i)
     
    for each IDDocument docColl in coll
    {
      docColl.setTag(NOLOGCHILD, true)
    }
  }
   
  boolean noLog = Doc.getTag(NOLOGCHILD)
   
  if (noLog == false)
  {
    if (!(Log.CreaLog(Doc)))
    {
      // Se non riesco a creare il log potrei annullare il salvataggio impostando Cancel = true in questo blocco di codice
    }
  }
}

```

Il metodo statico CreaLog del documento Log recupera i valori originali e salva il tutto nella tabella Logs.

```auto
boolean esito = false
IDDocument docOriginal = Log.RecuperaValoriOriginali(Doc)
string docXml = docOriginal.saveToXML(false, "", 9999, JSON, ...)
 
Log l = new()
l.init()
l.Document = docOriginal.typeName()
l.DateMod = now()
l.DocDNA = docOriginal.getDNA()
l.Record = docXml
 
esito = l.saveToDB(...)
return esito

```

Non sto a descrivere tutti metodi che sono presenti nel progetto ma era giusto per farvi vedere al volo che si possono fare cose simpatiche con la reflection di Instant Developer Foundation.

Comunque in questo modo abbiamo che quando un documento viene salvato causa una modifica viene scritto un record sulla tabella Logs.  
_Per il momento non è stata gestita la cancellazione di un record._

### Vediamo ora come possiamo far vedere queste modifiche.

Per prima cosa ho creato una videata che visualizza i record del documento Log (_LogsDoc_):

 ![image](https://community.instantdeveloper.com/uploads/default/original/1X/c45bd221523c39b744ed603e3509eae7f978e4e5.png)

Il contenuto del record prima della modifica è nel riquadro rosso ed è in formato JSON che è di poco aiuto per gli nostri dell’applicativo, ma in esso ci sono tutti i dati che ci occorrono per visualizzare un record in una videata.  
Come facciamo a visualizzare correttamente questi dati?

Per ogni documento ho creato una videata apposita con il solo dettaglio e in sola visualizzazione così da avere un posto specifico dove visualizzare ogni singolo documento.  
Nella videata _LogsDoc_ è stato gestito l’evento l’evento _OnActivatingRow_ che riporta questo codice:

```auto
Log l = Logs.document
 
if (l != null)
{
  IDDocument doc = IDDocument.getFromDNA(l.DocDNA, ...)
  doc.loadFromXML(l.Record, false, JSON, ...)
  doc.show(Popup)
  if (this.RichiamataDaMenu == false)
  {
    this.close(...)
  }
}

```

Qui prendo il documento attivo dal pannello e poi instanzio un _IDDocument_ (il documento base da cui ereditano tutti i documenti) e con il metodo _getFromDNA()_ ne creo la struttura in memoria nella variabile _doc_.  
Poi carico i suoi dati dal campo del record di Log preso dal video e a questo punto posso usare il metodo show() del documento che lo porterà a video nella videata di default del documento stesso.

La videata di default di un documento è quella che è stata creata per prima con il drag & drop per quel documento ed è possibile cambiare questa impostazione come spiegato più sotto.

Nel progetto ho creato le videate per visualizzare i dati prima della modifica dei miei documenti e sono quelle che _Vis_ alla fine del nome e sono impostate solo per visualizzare un record in dettaglio.

Cliccando con il tasto destro del mouse su di una videata si vede a quale classe è collegata perché sono presenti i comandi _Vai alla classe xxx_ e _Stacca dalla classe xxx_.  
Per cambiare la videata predefinita si deve trascinare la nuova videata (che vuoi diventi quella predefinita) sul documento tenendo premuto il tasto il tasto SHIFT.

Questo un esempio di videata per visualizzare il record di Log.

 ![image](https://community.instantdeveloper.com/uploads/default/original/1X/eafc28bef2d72663053b98aa56d8356413284189.png)

Nell’immagine si vede che il campo _Shipped Date_ ha il testo di colore rosso ad indicare che quello è il valore modificato rispetto al documento attuale.  
Questa finezza è realizzata dal metodo _confrontaDocs_ della classe _DocHelper_.

```auto
if (doc != null && docPrec != null)
{
  IDDocumentStructure ds = doc.getStructure() // 
  // 
  for (int i = 1; i <= ds.getPropertyCount(); i = i + 1)
  {
    string value = doc.getProperty(i)
    string valuePrec = docPrec.getProperty(i)
    if (value != valuePrec)
    {
      IDPropertyDefinition pd = ds.getPropertyDefinition(i)
      // 
      for (int k = 0; k < pan.fieldsCount(); k = k + 1)
      {
         if (pan.getFieldDBCode(k) == pd.DBCode)
         {
           pan.setFieldTextColor(k, RGBColor(255, 0, 0, ...))
           break 
         }
      }
    }
  }
}

```

Questo metodo riceve tre parametri:

- doc - la versione attuale del documento
- docPrev - la versione precedente del documento
- pan - il pannello dove viene visualizzato il docPrev

Per ora il metodo _confrontaDocs_ non va a verificare i documenti figli ma lo sistemo quanto prima.

La descrizione di questo esempio non è completa ma almeno con quello che ho scritto vi saprete orientare al suo interno e poi con vostri consigli posso migliorarlo.

---

<div class="post-metadata">

**Author:** ![r.bianco](https://community.instantdeveloper.com/user_avatar/community.instantdeveloper.com/r.bianco/32/41_2.png) [@r.bianco](https://community.instantdeveloper.com/u/r.bianco)\
**Post date:** [5 Settembre 2025, 6:40am UTC](https://community.instantdeveloper.com/t/gestire-uno-storico-di-modifiche-ai-record-del-database-con-foundation/795/2 "2025-09-05T06:40:55Z")

</div>

Molto bello! Grazie Paolo.  
Due domande:  
Nal metodo _confrontaDocs_ della classe _DocHelper, pan_ come viene ricavato?  
Se cambia la struttura delle tabelle/campi db che succede?

---

<div class="post-metadata">

**Author:** ![d.termini](https://community.instantdeveloper.com/user_avatar/community.instantdeveloper.com/d.termini/32/199_2.png) [@d.termini](https://community.instantdeveloper.com/u/d.termini)\
**Post date:** [5 Settembre 2025, 6:45am UTC](https://community.instantdeveloper.com/t/gestire-uno-storico-di-modifiche-ai-record-del-database-con-foundation/795/3 "2025-09-05T06:45:06Z")

</div>

Bello, molto interessante, soprattutto il fatto di salvare a livello di padre tutta la gerarchia e il confronto.

Potrebbe avere qualche problema se si gestisce indipendentemente un figlio, cosa che di solito si fa lato codice su operazioni automatizzate, però per le modifiche da interfaccia dovrebbe essere sufficiente.

Oppure se un documento figlio ha 2 padri (es righe ordine per ordine e righe ordine per articolo) verrà registrato il log della gerarchia solo per il padre che aveva quando è stato modificato, quindi se lo confronto per il secondo padre non troverò modifiche oppure ne troverò più di quante dovrei a seconda di cosa è stato modificato (o ripristinato come valore).

---

<div class="post-metadata">

**Author:** ![paolo.giannelli](https://community.instantdeveloper.com/user_avatar/community.instantdeveloper.com/paolo.giannelli/32/12_2.png) [@paolo.giannelli](https://community.instantdeveloper.com/u/paolo.giannelli)\
**Post date:** [5 Settembre 2025, 6:51am UTC](https://community.instantdeveloper.com/t/gestire-uno-storico-di-modifiche-ai-record-del-database-con-foundation/795/4 "2025-09-05T06:51:01Z")

</div>

L’oggetto pan è passato come parametro al metodo ed è un _IDPanel_.  
Il metodo _ConfrontaDocs_ viene richiamato nell’evento _Activate_ della videata che visualizza il documento letto dalla tabella Logs.

Non ho provato a cambiare la struttura di una tabella aggiungendo un campo ma dovrebbe funzionare ugualmente, magari occorre mettere una protezione al codice.

Ribadisco che è un esempio da migliorare sicuramente ma ci mostra le potenzialità dei documenti e degli eventi globali di Instant Developer Foundation.

---

<div class="post-metadata">

**Author:** ![paolo.giannelli](https://community.instantdeveloper.com/user_avatar/community.instantdeveloper.com/paolo.giannelli/32/12_2.png) [@paolo.giannelli](https://community.instantdeveloper.com/u/paolo.giannelli)\
**Post date:** [5 Settembre 2025, 7:04am UTC](https://community.instantdeveloper.com/t/gestire-uno-storico-di-modifiche-ai-record-del-database-con-foundation/795/5 "2025-09-05T07:04:41Z")

</div>

Mi sono accorto adesso che avevo già scritto un post con questo argomento e questo esempio un po’ più grezzo…

Questo il link:

> [@Log di memorizzazione generica di modifica dei documenti](https://community.instantdeveloper.com/t/log-di-memorizzazione-generica-di-modifica-dei-documenti/150):
>
> Ho realizzato un esempio che serve a memorizzare in una apposita tabella (Logs) le modifiche ai documenti contenuti nell’applicazione ed a visualizzarli in modo generalizzato aggiungendo un custom command a tutte le videate. Descrizione Il cuore del meccanismo di salvataggio delle modifiche a tutti i documenti dell’applicazione sono gli eventi GlobalBeforeSave dei documenti e GlobalPanelCommand dei pannelli, oltre all’utilizzo della reflection di Instant Developer Foundation. Global…

Magari vedo se si riesce a unificare i post, sicuramente aggiorno l’esempio allegato all’ultima versione e cito questo post anche nell’altro.

L’età comincia a farsi sentire 🤔

---

<div class="post-metadata">

**Author:** ![d.termini](https://community.instantdeveloper.com/user_avatar/community.instantdeveloper.com/d.termini/32/199_2.png) [@d.termini](https://community.instantdeveloper.com/u/d.termini)\
**Post date:** [5 Settembre 2025, 7:29am UTC](https://community.instantdeveloper.com/t/gestire-uno-storico-di-modifiche-ai-record-del-database-con-foundation/795/6 "2025-09-05T07:29:43Z")

</div>

Tranquillo, non sei l’unico… e non mi è neanche venuto quel senso di deja vu 🤣

---

<div class="post-metadata">

**Author:** ![paolo.giannelli](https://community.instantdeveloper.com/user_avatar/community.instantdeveloper.com/paolo.giannelli/32/12_2.png) [@paolo.giannelli](https://community.instantdeveloper.com/u/paolo.giannelli)\
**Post date:** [5 Settembre 2025, 7:37am UTC](https://community.instantdeveloper.com/t/gestire-uno-storico-di-modifiche-ai-record-del-database-con-foundation/795/7 "2025-09-05T07:37:34Z")

</div>

Il post è di gennaio 2024 e l’ho anche cercato prima di scrivere. 😂

---

<div class="post-metadata">

**Author:** ![paolo.giannelli](https://community.instantdeveloper.com/user_avatar/community.instantdeveloper.com/paolo.giannelli/32/12_2.png) [@paolo.giannelli](https://community.instantdeveloper.com/u/paolo.giannelli)\
**Post date:** [2 Ottobre 2025, 8:04am UTC](https://community.instantdeveloper.com/t/gestire-uno-storico-di-modifiche-ai-record-del-database-con-foundation/795/8 "2025-10-02T08:04:28Z")

</div>

Ho cambiato categoria a questo articolo che è più corretto sia un esempio e non un Tips & Tricks.
