Laravel – modifiche ad un tracciato dati in una dashboard di dati Covid-19: come gestirle

Spread the love
Laravel vs SARS-Cov-2
Laravel vs SARS-Cov-2
Immagine del virus SARS-Cov-2 al

Nella gestione dei dati della pandemia da Covid-19, nel corso del tempo è successo che i gestori del flusso dati della Protezione Civile per ragioni di miglioramento della interpretazione edlla situazione, integrassero le colonne con nuove dimensioni. Ad esempio dal 18 gennaio 2021 sono stati introdotti dimensioni come il numero di tamponi rapidi, per distinguerli dai tamponi con test molecolare.

Questa modifica impatta nella base dati locale, che si maniene aggiornata quotidianamente, con l’aggiunta di una colonna ulteriore nel tracciato CSV reperibile nel repository pubblico ufficiale della Protezione Civile ospitato su Github, colonna che deve essere ospitata in una tabella relazionale che rispecchia la struttura del CSV.

Come adeguare il modello MVC al nuovo tracciato? Laravel consente di farlo in modo molto veloce.

Modifica al modello Laravel e alla tabella database

Si crea innanziatutto una nuova migrazione vuota:

$ php artisan make:migration tab_dati_nazionali_add_tampone_rapido

Il nome della migrazione è a piacere e deve ricordare l’operazione che svolgerà. Non serve che sia il nome esatto del campo (sono nomi lunghi e preferisco abbreviare).

Un nuovo file per la migrazione verrà quidi creato sotto la directory

app/database/migrations
-rw-rw-r-- 1 marcob marcob 822 gen 22 10:51 2021_01_22_095107_tab_dati_nazionali_add_tampone_rapido.php

Editiamo il file che si presenta così, con una nuova classe che è la versione camelCased del nome del file di migrazione:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class TabDatiNazionaliAddTamponeRapido extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        //
    }
}

La classe ha due metodi: uno up() per aggiungere il campo e uno che si chiama ovviamente down() per eliminarlo, nel caso in cui fosse necessario un rollback delle operazioni di modifica della struttura.

Dobbiamo quindi aggiungere l’istruzione PHP che verrà convertita in istruzione DDL dall’ORM. Il nome esatto del campo che verrà prelevato dal CSV è tamponi_test_antigenico_rapido ed è modellabile con un integer; lo sisteiamo appena dopo la colonna note_test:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class TabDatiNazionaliAddTamponeRapido extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //
        Schema::table('dati_nazionali', function (Blueprint $table) {
            //
            $table->integer('tamponi_test_antigenico_rapido', '0')
                ->after('note_test')
                ->default(0)
                ->nullable();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        //
        Schema::table('dati_nazionali', function (Blueprint $table) {
            //
            $table->dropColumn('tamponi_test_antigenico_rapido');
        });
    }
}

Ho creato a suo tempo una tabella dati_nazionali nel database che ospita i dati provenienti dai file CSV. Ora devo solo aggiungere una nuova colonna.

A questo punto è arrivato il momento di lanciare la migrazione

$ php artisan migrate
Migrating: 2021_01_22_095107_tab_dati_nazionali_add_tampone_molecolare
Migrated:  2021_01_22_095107_tab_dati_nazionali_add_tampone_molecolare (0.43 seconds)
$

Si può controllare la presenza del nuovo campo nella tabella dati nazionali:

mysql> desc italia;
+----------------------------------------+-----------------+------+-----+---------+-----------+
| Field                                  | Type            | Null | Key | Default | Extra     |
+----------------------------------------+-----------------+------+-----+---------+-----------+
| id                                     | bigint unsigned | NO   | PRI | NULL    | auto_inc..|
| data                                   | datetime        | NO   | UNI | NULL    |           |
| stato                                  | varchar(255)    | NO   |     | NULL    |           |
| ricoverati_con_sintomi                 | int unsigned    | YES  |     | NULL    |           |
| terapia_intensiva                      | int unsigned    | YES  |     | NULL    |           |
| ingressi_terapia_intensiva             | int             | YES  |     | 0       |           |
| totale_ospedalizzati                   | int unsigned    | YES  |     | NULL    |           |
| isolamento_domiciliare                 | int unsigned    | YES  |     | NULL    |           |
| totale_positivi                        | int unsigned    | YES  |     | NULL    |           |
| variazione_totale_positivi             | int             | YES  |     | NULL    |           |
| nuovi_positivi                         | int unsigned    | YES  |     | NULL    |           |
| dimessi_guariti                        | int unsigned    | YES  |     | NULL    |           |
| deceduti                               | int unsigned    | YES  |     | NULL    |           |
| casi_da_sospetto_diagnostico           | int             | YES  |     | 0       |           |
| casi_da_screening                      | int             | YES  |     | 0       |           |
| totale_casi                            | int unsigned    | YES  |     | NULL    |           |
| tamponi                                | int unsigned    | YES  |     | NULL    |           |
| casi_testati                           | int unsigned    | YES  |     | NULL    |           |
| note                                   | varchar(255)    | YES  |     | NULL    |           |
| note_casi                              | longtext        | YES  |     | NULL    |           |
| note_test                              | longtext        | YES  |     | NULL    |           |
| tamponi_test_antigenico_rapido         | int             | YES  |     | 0       |           |
| tamponi_test_molecolare                | int             | YES  |     | 0       |           |
| totale_positivi_test_antigenico_rapido | int             | YES  |     | 0       |           |
| totale_positivi_test_molecolare        | int             | YES  |     | 0       |           |
| created_at                             | timestamp       | YES  |     | NULL    |           |
| updated_at                             | timestamp       | YES  |     | NULL    |           |
+----------------------------------------+-----------------+------+-----+---------+-----------+
27 rows in set (0.01 sec)

Come si può vedere, il campo tamponi_test_antigenico_rapido è un intero ed è satato inserito dopo il campo note_test come richiesto.

Finito!

E se qualcosa va storto?

Si può sempre tornare indietro facendo un rollback: artisan eseguirà il metodo down() della classe che viene tradotto con un alter table remove column.

$ php artisan migrate:rollback

Gestione della view e dell’importatore Laravel

In questo caso ho scelto di non mostrare nella tabella anche il nuovo dato, ma se si volesse è sufficiente modificare la view

app/resources/views/dati_nazionali/index.blade.php

aggiungendo una colonna nella riga di intestazione

    <table class="table table-hover text-centered">
            <thead>
                <th>data</th>
               ...
                <th>totale</th>
                <th>tamponi molecolari</th>
                <th>tamponi rapidi</th> <-------
               ...

e il segnaposto per il dato nel ciclo

@foreach($array['data'] as $item)
                <tr>
                    <td>{{$item->data}}</a></td>
                    ...
                    <td>{{$item->tamponi_test_molecolare}}</a></td>
                    <td>{{$item->tamponi_test_antigenico_rapido}}</a></td>
                    ...

Nle mio caso non l’ho integrato per pigrizia (mi interessa maggiormanete che il processo di importazione giri senza problemi ogni giorno), ma appena posso lo integro nella vista.

Ultimo step: l’estrattore da CSV

L’ultimo passaggio è l’esecuzione giornaliera dell’importatore: una riga di cron lancia lo script Laravel che si connette via Curl (vedi l’articolo sui problemi della libreria Ixudra che implememta il client cURL http) al repository Github e scrive le nuove righe nelle tabelle dei dati nazionali e regionali.

Questo script non ho dovuto modificarlo perché l’ho già scritto in modo dinamico: il parser estrae i dati leggendo le colonne del csv e cercando le colonne omonime nella tabella, per cui è già tutto ok.

Sito della situazione Covid-19 di betaingegneria.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.