Drupal: propagazione automatica di dati in una gerarchia

Con Drupal si possono creare vere e proprie applicazioni web based orientate alla gestione di dati, molto spesso senza scrivere un rigo di codice. Gli appunti che seguono nascono da esperimenti svolti da me, debitamente astratti per facilitarne il riuso in progetti differenti.

Data una struttura gerarchica di nodi, ognuno dotato di un dato numerico, vogliamo sommare ai livelli superiori i dati dei livelli inferiori. Ecco due possibili esempi di applicazione di questo esperimento:

gerarchia  dato da propagare 
Italia – Regioni – Provincie – Comuni numero abitanti
Casa madre – Distributore sub nazionale – Distributore regionale – Filiale locale fatturato

Vediamo come predisporre la gerarchia e, soprattutto, come istruire Drupal perché, aggiornando un valore in un nodo, questo valore si propaghi automaticamente verso l’alto.

CREAZIONE E NAVIGAZIONE GERARCHIA

Creiamo in Drupal un nuovo tipo di contenuto (es. “Filiale”) dotato di almeno due campi:

  • un campo “fatturato” di tipo decimale, che conterrà il valore del fatturato
  • un campo “superiore” di tipo entity reference che punterà alla Filiale gerarchicamente superiore

e poi creiamo tutti i nodi Filiale che ci servono, es. “Italia”, “Nord Est” (con superiore = “Italia”), “Veneto” (con superiore = “Nord Est”) ecc. Con ciò la gerarchia è pronta. Per facilitarne la navigazione suggerisco di creare, col modulo “EVA”, una vista richiamata nella visualizzazione dei nodi di tipo Filiale e che elenchi per quella Filiale tutte le sue subfiliali e i fatturati corrispondenti. L’effetto sarà il seguente:

NORD EST
Filiale superiore: Italia
Fatturato: 350.000
FILIALE
FATTURATO
Veneto
100.000
Trentino Alto Adige
200.000
Friuli Venezia Giulia
50.000

Cliccando su “Filiale superiore” si risale la gerarchia fino al nodo privo di nodo superiore (nell’esempio, il nodo “Italia”) che dovrà avere come valore del fatturato la somma dei fatturati sottostanti. Cliccando su una delle Filiali elencate, si scende di un livello nella gerarchia, spezzando il fatturato in cifre sempre più piccole e locali, operando quindi una sorta di “drill down” di analisi del fatturato. Ciò naturalmente ha senso solo se qualcosa “magicamente” tiene allineati i dati dal basso verso l’alto. Vediamo cosa.

PROPAGAZIONE DEI DATI DAL BASSO VERSO L’ALTO

In Drupal ci sono diversi modi per automatizzare la valorizzazione di un campo (es. Computed Field) o la sua sola rappresentazione (es. Views Aggregation Plus) ma volendo assicurarsi che in ogni momento i valori siano allineati ho preferito utilizzare le Rules. La soluzione consiste quindi nel scrivere una Rule che,  quando si modifica un nodo N di tipo Filiale (es. “Milano”):

  1. Identifichi il nodo S superiore al nodo N (es. “Lombardia”)
  2. Identifichi tutti i figli F del nodo S (es. “Milano”, “Bergamo”, “Brescia” ecc.)
  3. Sommi i fatturati dei figli F e scriva la somma nel fatturato del nodo S
  4. Risalga la gerarchia ripartendo dal passo 1, stavolta avendo come N il nodo S

Partendo dal nodo modificato, questa Rule aggiorna i fatturati delle filiali sovrastanti (“Lombardia” – “Nord Est” – “Italia”) fino ad arrivare al nodo apicale, dove si ferma perché non esiste il nodo S. Ovviamente questo metodo presuppone che i nodi intermedi non fatturino e che sia vietato alterare a mano i fatturati di questi nodi (la protezione del campo fatturato per questi nodi può essere realizzata in molti modi, che non affrontiamo qui).

Come si realizza una Rule di questo genere?

Purtroppo la scrittura di una Rule in Drupal non è sempre una passeggiata: le AVVERTENZE che seguono cercano di offrire un aiuto a superare ostacoli altrimenti di difficile comprensione.

Anzitutto ho scritto un “Component” di tipo “Rules” (che non è la stessa cosa che scrivere una “Rule” e già qui si capisce che muoversi nell’ambiente non è del tutto agevole….): in pratica questo tipo di Rule è una routine, con parametri di ingresso e uscita. Questa Component “CalcolaFatturato” prende come input un nodo N (il nodo di cui aggiornare il fatturato, calcolato come somma dei suoi figli) e restituisce il nodo superiore S, se esiste. Vediamo i dettagli:

  1. inizializza una variabile HaFigli= 0 (serve per sapere alla fine se il nodo N ha figli oppure no e, in caso positivo, assegnargli come fatturato la somma dei fatturati dei figli; serve per evitare di piallare il fatturato dei nodi “terminali” della gerarchia)
  2. inizializza una variabile FatturatoFigli=0
  3. esegue un ciclo sui figli F del nodo N; nel ciclo, legge il fatturato di ogni figlio F e lo somma a FatturatoFigli; mette HaFigli=1
  4. al termine del ciclo, se HaFigli=1 scrive nel campo fatturato di N il valore FatturatoFigli
  5. esamina il campo “superiore” del nodo N e ne carica il valore nel parametro di uscita S

AVVERTENZA per il passo 3: la soluzione più semplice per realizzare questo ciclo è installare il modulo “Views Rules”, che aggiunge alle Rules il ciclo di tipo “Views Loop”, che permette di fare dei cicli sui nodi risultanti da una View, in questo caso la medesima View che abbiamo visto più sopra elencare i nodi figli di una filiale

AVVERTENZA ai passi 3 e 5: perché sia possibile accedere ad un campo di un nodo, è necessario anteporre alla lettura o scrittura del campo la verifica della sua esistenza mediante una apposita condizione del tipo “Se l’entità ha il campo…”; se non si esegue questa verifica, il campo NON sarà disponibile nell’editor della Rules.  Questo è un limite delle Rules che mi ha fatto perder tempo finché non l’ho capito. Per accedere ai campi del nodo N basta quindi mettere nella sezione “condizioni” del Component le due condizioni  “L’entità N ha il campo fatturato?” e “L’entità N ha il campo superiore?”.

Il problema sorge al passo 3, dove si vuole accede al campo fatturato di diversi nodi F, non controllabili dalla sezione “condizioni” del Component in quanto sono via via forniti dalla view. La soluzione che ho trovato è eseguire il passo 3 richiamando un altro Component che, ricevuto in input il nodo F, al suo interno abbia la condizione “L’entità F ha il campo fatturato?”, acceda a quel campo e ne restituisca il valore come output. Scritto questo Component “LeggiFatturato”, il passo 3 diventa il seguente:

3. esegue un ciclo (view loop) su figli F del nodo N: nel ciclo, esegue il Component LeggiFatturato su F e somma in FatturatoFigli il valore restituito da LeggiFatturato

Scritta la Component “CalcolaFatturato” (e la sua ancella “LeggiFatturato”), completiamo l’opera scrivendo la Rule vera e propria, che a questo punto è abbastanza semplice:

Rule attivata quando viene modificato un nodo N di tipo Filiale

  1. Salva il nodo N (il motivo lo spiego dopo)
  2. Inizializza una variabile C di tipo nodo e la mette uguale a N
  3. Esegue un ciclo di tipo WHILE finché C non è nullo (per realizzare questo tipo di ciclo occorre installare il modulo “Conditional Rules”; probabilmente si può farne a meno realizzando un “loop” standard ma sono pigro e ho preferito questa soluzione più leggibile)
  4. nel ciclo, esegue il Component “CalcolaFatturato” applicato al nodo C
  5. sempre nel ciclo, assegna a C il valore S restituito da CalcolaFatturato (queto passaggio permette di risalire la gerarchia)

AVVERTENZA sul passo 1: la Rule viene attivata appena si clicca “Salva” sul nodo N, ma i nuovi valori di N (tra cui il fatturato) non vengono realmente scritti nel database fintanto che la Rule non è terminata. All’interno della Rule i valori sono giusti, ma fuori di essa no. Perciò il Component “CalcolaFatturato” lanciato dalla Rule vede ancora il vecchio valore di fatturato di N, sbagliando di conseguenza il calcolo dei fatturati dei nodi sovrastanti. Per evitare questo errore, è necessario nella Rule principale forzare il salvataggio immediato di N nel database, per essere sicuri che CalcolaFatturato veda il valore aggiornato.

Al di là del caso specifico, un bell’esercizio per capire tante cose del nostro CMS preferito.

6 pensieri su “Drupal: propagazione automatica di dati in una gerarchia

  1. After going over a few of the blog articles on your web site, I really like your technique of blogging. I bookmarked it to my bookmark website list and will be checking back soon. Take a look at my website as well and tell me what you think.

    Mi piace

  2. Magnificent beat ! I would like to apprentice while you amend your web site, how can i subscribe for a weblog site? The account helped me a appropriate deal. I had been a little bit familiar of this your broadcast offered bright transparent concept

    Mi piace

  3. Wonderful goods from you, man. I’ve have in mind your stuff prior to and you are simply too great. I actually like what you’ve got here, really like what you are stating and the way in which in which you are saying it. You are making it entertaining and you continue to care for to stay it sensible. I can’t wait to learn far more from you. This is really a tremendous website.

    Mi piace

  4. Hello, i believe that i noticed you visited my website thus i came to return the favor?.I am attempting to in finding issues to enhance my website!I assume its ok to make use of a few of your ideas!!

    Mi piace

Lascia un commento

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...