Tutti i progetti scolastici

Prenotazioni APRA

Sistema per prenotare uffici e sale riunioni nella sede aziendale, sviluppato durante il percorso di alternanza scuola-lavoro in APRA S.p.A. Un'app Flutter multipiattaforma davanti, un'API REST in .NET dietro, il tutto in container su un server Linux.

Contesto
PCTO in APRA S.p.A.
Anno
2026
Ruolo
Sviluppo completo, frontend e backend
Stack
Flutter · ASP.NET Core · PostgreSQL · Docker
Stato
In esecuzione su server di prova
Piantina degli spazi: riquadri verdi per ufficio e sala con posti totali e liberi, filtri per tipo e piano in alto e selettore della data.
La piantina: stato di ogni spazio a colpo d'occhio, con filtri per tipo, piano e posti minimi
Schermata Le mie prenotazioni: calendario settimanale di giugno 2026 con i blocchi blu degli uffici e verdi delle sale riunioni.
Le mie prenotazioni: settimana, giorno o mese, uffici in blu e sale riunioni in verde

Descrizione del progetto

I dipendenti prenotano una postazione o una sala riunioni; il sistema distingue tre livelli di utente con permessi crescenti.

  • Standard — accesso, prenotazione, gestione delle proprie prenotazioni, cambio password.
  • Admin — in piu': anagrafica dipendenti, gestione di uffici e sale, tutte le prenotazioni, statistiche di utilizzo.
  • Superadmin — in piu': promozione e retrocessione degli amministratori.

La schermata principale e' una piantina unificata che mostra lo stato di ogni spazio (libero, parzialmente occupato, occupato) con filtri per tipo, piano e numero minimo di posti. Il calendario permette di creare una prenotazione trascinando sull'orario: in giornata singola, su un intervallo di date o ricorrente su determinati giorni della settimana.

Pannello amministratore, scheda Spazi: elenco dei 52 uffici con piano e numero di posti, con i pulsanti di modifica e cancellazione e il bottone Aggiungi ufficio.
Pannello amministratore: anagrafica di uffici e sale, con modifica e cancellazione
Pannello amministratore, scheda Persona: campo di ricerca del dipendente e calendario settimanale con le sue prenotazioni di uffici e sale.
Scheda Persona: le prenotazioni di un singolo dipendente, cercato per nome

Tech stack

Architettura client-server classica: il frontend parla con il backend via HTTP scambiando JSON. In produzione Nginx fa da reverse proxy: la radice serve l'applicazione Flutter compilata per il web, il percorso /api/ viene inoltrato all'API in ascolto nel container.

Runtime.NET 10
FrameworkASP.NET Core, pattern Minimal API
ORMEntity Framework Core con provider Npgsql
DatabasePostgreSQL 16
FrontendFlutter, un solo progetto per web, Android e Windows
AutenticazioneJWT firmati HS256, password con BCrypt
InfrastrutturaDocker Compose + Nginx su Debian

Gli endpoint sono registrati come funzioni, senza classi controller: ogni percorso e' una funzione con i suoi ingressi e la sua risposta. Le tabelle sono definite come classi C# e le migrazioni vengono generate da quelle e applicate all'avvio, quindi il database si allinea da solo al codice senza script SQL scritti a mano.

Tutto il backend e' containerizzato: un container per l'API, uno per il database e uno per l'interfaccia di amministrazione del database. I dati vivono in un volume nominato, cosi' ricostruire i container non cancella nulla.

La stessa piantina aperta nel browser con il tema chiaro: fascia dei filtri in alto, riquadri verdi degli uffici e delle sale divisi per piano.
Lo stesso progetto Flutter compilato per il web e servito da Nginx, qui con il tema chiaro

Problema risolto

In sede le sale riunioni si prenotavano con il metodo piu' vecchio del mondo: chiedere. Il risultato erano riunioni con due gruppi davanti alla stessa porta, sale bloccate da prenotazioni mai disdette e nessun modo di sapere quali spazi fossero davvero usati.

La richiesta dell'azienda era vedere lo stato reale degli spazi a colpo d'occhio e prenotare in pochi secondi, dal computer o dal telefono. Da qui due scelte: la piantina come schermata principale, perche' una mappa si legge piu' in fretta di un elenco, e Flutter al posto di un framework solo web, perche' la stessa base di codice doveva servire il browser dei dipendenti e l'app sul telefono senza scriverla due volte.

Dal mio lato serviva un'altra cosa: un progetto vero, con un committente vero, portato fino a girare su un server e non fino al tasto Esegui.

Pannello amministratore, scheda Statistiche: numero di prenotazioni, ore ufficio, durata media, uffici attivi e due grafici ad anello con gli uffici piu' prenotati e le sale piu' usate.
Le statistiche di utilizzo: la risposta alla domanda "quali spazi vengono davvero usati"

Le procedure

Essendo un progetto aziendale, il modo di lavorare era parte della consegna quanto il codice.

  • Raccolta dei requisiti — incontro iniziale con il tutor aziendale per capire chi usa il sistema e cosa deve poter fare. Da li' sono usciti i tre livelli di utente e le regole sui permessi.
  • Analisi e modello dei dati — prima le entita' e le relazioni (spazi, dipendenti, prenotazioni, ricorrenze), poi il codice. Le tabelle sono nate su carta e sono diventate classi C#.
  • Sviluppo a incrementi — prima l'autenticazione, poi la prenotazione singola, poi intervalli e ricorrenze, infine amministrazione e statistiche. Ogni pezzo funzionante prima di passare al successivo.
  • Versionamento — repository Git con un branch dedicato alla versione containerizzata, tenuto separato da quello di sviluppo locale finche' il deployment non era stabile.
  • Verifica — prove sui casi limite: prenotazioni sovrapposte, ricorrenze che cadono su giorni gia' occupati, utente retrocesso mentre e' collegato, token scaduto.
  • Messa in esecuzione — accesso al server via SSH, build delle immagini, avvio con Docker Compose, configurazione di Nginx come reverse proxy e verifica che i dati sopravvivessero alla ricostruzione dei container.
  • Consegna — presentazione del funzionamento al tutor e documentazione delle procedure di avvio e aggiornamento, perche' il progetto dovesse restare utilizzabile anche senza di me.

Sul fronte dell'applicazione le procedure principali sono tre e sono tutte tracciate: creazione di una prenotazione con controllo di conflitto prima della conferma, promozione o retrocessione di un amministratore riservata al superadmin, e cambio password con reimpostazione forzata al primo accesso.

Nozioni apprese

  • Cosa significa “andare in produzione” — e' il primo progetto che ho portato fino al deployment vero: SSH sul server, build dei container, reverse proxy, volumi persistenti. Prima di questo, per me, mandare in produzione finiva con il tasto Esegui.
  • Docker non e' un dettaglio — separare API, database e strumenti in container distinti, e capire che il volume nominato e' l'unica ragione per cui ricostruire tutto non cancella i dati.
  • Autenticazione con token — firmare un JWT, farlo scadere, verificarlo a ogni richiesta e non salvare mai una password in chiaro: BCrypt, con il suo costo di calcolo, esiste apposta.
  • Migrazioni invece di SQL a mano — il database che si allinea al codice all'avvio dell'applicazione elimina un'intera categoria di errori da “ho dimenticato di aggiornare la tabella sul server”.
  • Una base di codice, tre piattaforme — lo stesso progetto Flutter che produce web, Android e Windows, con le differenze concentrate in pochi punti.
  • Lavorare per qualcun altro — un requisito dato da un'azienda non si negozia riscrivendolo: si chiarisce prima e si rispetta dopo. E' la differenza piu' grande rispetto ai progetti personali.