Browse Source

Update documentation and database schema for meal reservation system

- Enhanced README and idea documentation with detailed system architecture and operational flows.
- Revised database schema to simplify table structures and improve data handling with JSONB.
- Added state management for reservations in the schema.
- Updated requirements file to include necessary dependencies.
master
Matteo Benedetto 7 months ago
parent
commit
a394ed9ad2
  1. 114
      README.md
  2. 236
      idea.md
  3. 7
      requirements.txt
  4. 11
      schema.sql

114
README.md

@ -0,0 +1,114 @@
# Sistema di Prenotazione Mensa - Documentazione Tecnica
## Abstract
Il sistema di prenotazione mensa è una piattaforma web-based sviluppata, con FastAPI e PostgreSQL a livello backend e NiceGUI per le interfacce fullstack, che consente agli utenti di prenotare pasti giornalieri. L'architettura è basata su un'API RESTful con autenticazione JWT, garantendo sicurezza e scalabilità. Il sistema gestisce tr entità principali interconnesse: prenotazioni, pasti e pietanze, utilizzando campi JSON per semplificare le relazioni e migliorare le erformance. I dati utente sono forniti dal JWT auth bearer evittando la memorizzazione sul database di dati sensibili non necessari, sfruttando per questa funzionalità lo IAM Azure e l'account aziendale (o anche IAM self hosted Keycloak)
## Architettura del Sistema
### Stack Tecnologico
- **Backend**: FastAPI (Python 3.8+)
- **Database**: PostgreSQL 13+ con supporto JSON/JSONB
- **Autenticazione**: JWT (JSON Web Tokens) / OpenID-Connect (provider Azure o self-hosted)
- **HMI**: webgui fullstack NiceGUI (Python 3.9+)
## Database Design
### Filosofia di Semplificazione
Il database è stato progettato seguendo una filosofia di **massima semplificazione**, riducendo la complessità relazionale tradizionale attraverso l'uso strategico di campi JSONB di PostgreSQL al posto di tabelle intermedie per le relazioni N a N. Contestalmente alla semplicità dello scheme e alle potenti capacità di manipolazione di dati strutturati JSON di postgresql, questa scelta progettuale offre diversi vantaggi:
- **Riduzione delle JOIN**: Eliminazione di tabelle di associazione complesse
- **Flessibilità**: Strutture dati dinamiche per allergeni, turni e selezioni delle pietanze
- **Performance**: Meno query multiple per operazioni comuni
- **Manutenibilità**: Schema più leggibile e modificabile
### Struttura delle Tabelle
#### Tabella `pietanze`
Gestisce le singole pietanze disponibili con:
- Informazioni base (nome, descrizione)
- Gestione allergeni tramite array JSON
- Controllo disponibilità e limiti di prenotazione
#### Tabella `pasti`
Rappresenta i menu giornalieri con:
- **Portate JSONB**: Organizzazione flessibile delle pietanze per tipologia indicando la disponibilità massima di ciascuna
- **Turni JSONB**: Gestione dinamica degli orari e capacità (`{"12:45": 100, "13:30": 100}`)
- Vincolo di unicità per data e tipo pasto
#### Tabella `prenotazioni`
Collega utenti e pasti con:
- Riferimento user_id estratto da JWT
- **Pietanze selezionate JSONB**: Array delle scelte dell'utente
- Gestione stati del ciclo di vita della prenotazione
## Flussi Operativi
### Flusso di Creazione Menu Giornaliero
1. **Inserimento Pietanze**: Caricamento delle pietanze disponibili per il giorno
2. **Composizione Pasto**: Associazione pietanze alle portate tramite JSON
3. **Configurazione Turni**: Definizione orari e capacità massima per turno
4. **Attivazione**: Abilitazione delle prenotazioni per gli utenti
### Flusso di Prenotazione Utente
1. **Autenticazione**: Verifica JWT e estrazione user_id
2. **Visualizzazione Menu**: Recupero pasti disponibili per data
3. **Selezione Pietanze**: Scelta pietanze per ogni portata disponibile
4. **Validazione**: Controllo disponibilità e limiti di prenotazione
5. **Conferma**: Creazione record prenotazione con stato 'attiva'
### Flusso di Servizio Mensa
1. **Consultazione Prenotazioni**: Visualizzazione prenotazioni per turno
2. **Erogazione Pasto**: Aggiornamento stato da 'attiva', 'servita', 'pagata', 'completata'
3. **Monitoraggio**: Tracking utilizzo e disponibilità residua
### Flusso di Gestione Disponibilità
1. **Controllo Automatico**: Verifica limiti pietanze e turni
2. **Aggiornamento Dinamico**: Modifica disponibilità in tempo reale
3. **Notifiche**: Gestione comunicazioni per esaurimento posti
4. **Chiusura Prenotazioni**: Disabilitazione automatica al raggiungimento limiti
## Scelte Architetturali: Logica di Business
### Principio di Separazione delle Responsabilità
In linea con la filosofia di semplificazione adottata per il design del database, **la logica di business complessa rimane interamente gestita a livello API (FastAPI)** piuttosto che essere delegata al database tramite stored procedures o funzioni PostgreSQL.
#### Motivazioni della Scelta
**Coerenza Architetturale**: Il sistema è progettato attorno a FastAPI come orchestratore centrale. Mantenere la logica di business nell'API garantisce un'architettura coerente e predicibile.
**Manutenibilità e Testabilità**: Le funzioni Python sono intrinsecamente più facili da testare, debuggare e modificare rispetto alle stored procedures. Questo si allinea con l'approccio DevOps moderno e l'integrazione continua.
**Flessibilità di Sviluppo**: La gestione della disponibilità, dei limiti di prenotazione e delle validazioni può evolvere rapidamente senza modifiche al schema database.
#### Implementazione delle Verifiche di Disponibilità
Le operazioni critiche come la verifica di disponibilità posti in un turno o di una pietanza vengono gestite tramite:
- **Query atomiche** per il recupero dati
- **Validazioni Python** per la logica di business
- **Transazioni asyncpg** per garantire consistenza
- **Pattern async/await** per performance ottimali
### Scelta di asyncpg vs ORM
Il sistema utilizza **asyncpg** come driver database principale invece di un ORM tradizionale come SQLAlchemy per diverse ragioni strategiche:
#### Motivazioni Tecniche
**Ottimizzazione Nativa PostgreSQL**: La progettazione è strettamente legata alle funzionalità specifiche di PostgreSQL (JSONB, operatori JSON, funzioni aggregate native). Asyncpg consente di sfruttare al massimo queste capacità senza astrazioni intermedie.
**Performance Async Native**: Asyncpg è progettato specificamente per l'ecosistema async/await di Python, offrendo performance superiori rispetto agli adapter asincroni degli ORM tradizionali.
**Controllo Granulare**: Le query SQL dirette permettono un controllo preciso delle operazioni JSONB, essenziali per la gestione delle portate, turni e selezioni pietanze.
**Semplicità Architetturale**: Con solo tre tabelle e logica di business in Python, l'overhead di un ORM completo risulterebbe sproporzionato rispetto ai benefici.
#### Implementazione Pratica
- **Query ottimizzate** per operazioni JSONB specifiche
- **Pool di connessioni** gestito nativamente da asyncpg
- **Transazioni esplicite** per operazioni critiche di prenotazione
- **Prepared statements** per query ripetitive ad alta frequenza

236
idea.md

@ -2,7 +2,7 @@
## Abstract
Il sistema di prenotazione mensa è una piattaforma web-based sviluppata con FastAPI e PostgreSQL che consente agli utenti di prenotare pasti giornalieri. L'architettura è basata su un'API RESTful con autenticazione JWT, garantendo sicurezza e scalabilità. Il sistema gestisce quattro entità principali interconnesse: prenotazioni, pasti, pietanze e ingredienti, utilizzando campi JSON per semplificare le relazioni e migliorare le performance.
Il sistema di prenotazione mensa è una piattaforma web-based sviluppata, con FastAPI e PostgreSQL a livello backend e NiceGUI per le interfacce fullstack, che consente agli utenti di prenotare pasti giornalieri. L'architettura è basata su un'API RESTful con autenticazione JWT, garantendo sicurezza e scalabilità. Il sistema gestisce tr entità principali interconnesse: prenotazioni, pasti e pietanze, utilizzando campi JSON per semplificare le relazioni e migliorare le erformance. I dati utente sono forniti dal JWT auth bearer evittando la memorizzazione sul database di dati sensibili non necessari, sfruttando per questa funzionalità lo IAM Azure e l'account aziendale (o anche IAM self hosted Keycloak)
## Architettura del Sistema
@ -13,168 +13,82 @@ Il sistema di prenotazione mensa è una piattaforma web-based sviluppata con Fas
- **Autenticazione**: JWT (JSON Web Tokens)
- **ORM**: SQLAlchemy
### Componenti Principali
## Database Design
1. **API Layer**: Gestione endpoint REST con FastAPI
2. **Authentication Layer**: Middleware JWT per sicurezza
3. **Business Logic Layer**: Logica di prenotazione e validazione
4. **Data Access Layer**: SQLAlchemy ORM per accesso ai dati
5. **Database Layer**: PostgreSQL con schema relazionale
### Filosofia di Semplificazione
## Schema Database
Il database è stato progettato seguendo una filosofia di **massima semplificazione**, riducendo la complessità relazionale tradizionale attraverso l'uso strategico di campi JSONB di PostgreSQL al posto di tabelle intermedie per le relazioni N a N. Contestalmente alla semplicità dello scheme e alle potenti capacità di manipolazione di dati strutturati JSON di postgresql, questa scelta progettuale offre diversi vantaggi:
- **Riduzione delle JOIN**: Eliminazione di tabelle di associazione complesse
- **Flessibilità**: Strutture dati dinamiche per allergeni, turni e selezioni delle pietanze
- **Performance**: Meno query multiple per operazioni comuni
- **Manutenibilità**: Schema più leggibile e modificabile
### Struttura delle Tabelle
#### 1. Tabella `pietanze`
```sql
CREATE TABLE pietanze (
id SERIAL PRIMARY KEY,
nome VARCHAR(150) NOT NULL,
descrizione TEXT,
categoria VARCHAR(50), -- primo, secondo, contorno, dolce
prezzo DECIMAL(5,2),
disponibile BOOLEAN DEFAULT true,
ingredienti TEXT, -- Testo libero
allergeni JSONB, -- Array di allergeni: ["glutine", "lattosio", ...]
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
#### 2. Tabella `pasti`
```sql
CREATE TABLE pasti (
id SERIAL PRIMARY KEY,
data_pasto DATE NOT NULL,
tipo_pasto VARCHAR(20) NOT NULL, -- colazione, pranzo, cena
disponibile BOOLEAN DEFAULT true,
turno VARCHAR(20) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(data_pasto, tipo_pasto)
);
```
#### 3. Tabella `prenotazioni`
```sql
CREATE TABLE prenotazioni (
id SERIAL PRIMARY KEY,
user_id VARCHAR(100) NOT NULL, -- Estratto dal JWT
pasto_id INTEGER REFERENCES pasti(id) ON DELETE CASCADE,
pietanze_selezionate JSONB, -- Lista di pietanze
note TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(user_id, pasto_id)
);
```
## Endpoint API - Prenotazione Pasti
### 1. Creazione di una prenotazione
**POST /api/prenotazioni**
- **Descrizione**: Crea una nuova prenotazione per un pasto specifico.
- **Corpo della richiesta**:
```json
{
"pasto_id": 1,
"pietanze_selezionate": [
2,86,89
],
"note": "Senza glutine"
}
```
- **Risposta**:
- **201 Created**:
```json
{
"id": 42,
"user_id": "utente123",
"pasto_id": 1,
"stato": "attiva",
"pietanze_selezionate": [
{ "id": 1, "quantita": 1 },
{ "id": 3, "quantita": 2 }
],
"note": "Senza glutine",
"created_at": "2023-10-01T12:00:00Z",
"updated_at": "2023-10-01T12:00:00Z"
}
```
- **400 Bad Request**: Errore di validazione o dati mancanti.
---
### 2. Recupero delle prenotazioni di un utente
**GET /api/prenotazioni**
- **Descrizione**: Recupera tutte le prenotazioni dell'utente autenticato.
- **Risposta**:
- **200 OK**:
```json
[
{
"id": 42,
"pasto_id": 1,
"stato": "attiva",
"pietanze_selezionate": [
{ "id": 1, "quantita": 1 },
{ "id": 3, "quantita": 2 }
],
"note": "Senza glutine",
"created_at": "2023-10-01T12:00:00Z",
"updated_at": "2023-10-01T12:00:00Z"
}
]
```
---
### 3. Annullamento di una prenotazione
**PUT /api/prenotazioni/{id}/annulla**
- **Descrizione**: Annulla una prenotazione esistente.
- **Risposta**:
- **200 OK**:
```json
{
"id": 42,
"stato": "cancellata",
"updated_at": "2023-10-01T12:30:00Z"
}
```
- **404 Not Found**: Prenotazione non trovata.
---
### 4. Recupero dei pasti disponibili
**GET /api/pasti**
- **Descrizione**: Recupera i pasti disponibili per la prenotazione.
- **Parametri query**:
- `data` (opzionale): Filtra per data specifica (formato YYYY-MM-DD)
- `tipo_pasto` (opzionale): Filtra per tipo di pasto (colazione, pranzo, cena)
- **Esempi**:
- `GET /api/pasti` - Tutti i pasti disponibili
- `GET /api/pasti?data=2023-10-02` - Pasti per il 2 ottobre 2023
- `GET /api/pasti?data=2023-10-02&tipo_pasto=pranzo` - Solo pranzi del 2 ottobre
- **Risposta**:
- **200 OK**:
```json
[
{
"id": 1,
"data_pasto": "2023-10-02",
"tipo_pasto": "pranzo",
"turno": "12:00-14:00",
"disponibile": true,
"posti_totali": 100,
"posti_prenotati": 20,
"pietanze_disponibili": [
{ "id": 1, "nome": "Lasagna", "prezzo": 8.50 },
{ "id": 2, "nome": "Insalata", "prezzo": 5.00 }
]
}
]
```
#### Tabella `pietanze`
Gestisce le singole pietanze disponibili con:
- Informazioni base (nome, descrizione)
- Gestione allergeni tramite array JSON
- Controllo disponibilità e limiti di prenotazione
#### Tabella `pasti`
Rappresenta i menu giornalieri con:
- **Portate JSONB**: Organizzazione flessibile delle pietanze per tipologia indicando la disponibilità massima di ciascuna
- **Turni JSONB**: Gestione dinamica degli orari e capacità (`{"12:45": 100, "13:30": 100}`)
- Vincolo di unicità per data e tipo pasto
#### Tabella `prenotazioni`
Collega utenti e pasti con:
- Riferimento user_id estratto da JWT
- **Pietanze selezionate JSONB**: Array delle scelte dell'utente
- Gestione stati del ciclo di vita della prenotazione
## Flussi Operativi
### Flusso di Creazione Menu Giornaliero
1. **Inserimento Pietanze**: Caricamento delle pietanze disponibili per il giorno
2. **Composizione Pasto**: Associazione pietanze alle portate tramite JSON
3. **Configurazione Turni**: Definizione orari e capacità massima per turno
4. **Attivazione**: Abilitazione delle prenotazioni per gli utenti
### Flusso di Prenotazione Utente
1. **Autenticazione**: Verifica JWT e estrazione user_id
2. **Visualizzazione Menu**: Recupero pasti disponibili per data
3. **Selezione Pietanze**: Scelta pietanze per ogni portata disponibile
4. **Validazione**: Controllo disponibilità e limiti di prenotazione
5. **Conferma**: Creazione record prenotazione con stato 'attiva'
### Flusso di Servizio Mensa
1. **Consultazione Prenotazioni**: Visualizzazione prenotazioni per turno
2. **Erogazione Pasto**: Aggiornamento stato da 'attiva' a 'servita'
3. **Gestione Pagamento**: Transizione finale a stato 'pagata'
4. **Monitoraggio**: Tracking utilizzo e disponibilità residua
### Flusso di Gestione Disponibilità
1. **Controllo Automatico**: Verifica limiti pietanze e turni
2. **Aggiornamento Dinamico**: Modifica disponibilità in tempo reale
3. **Notifiche**: Gestione comunicazioni per esaurimento posti
4. **Chiusura Prenotazioni**: Disabilitazione automatica al raggiungimento limiti
## Scelte Architetturali: Logica di Business
### Principio di Separazione delle Responsabilità
In linea con la filosofia di semplificazione adottata per il design del database, **la logica di business complessa rimane interamente gestita a livello API (FastAPI)** piuttosto che essere delegata al database tramite stored procedures o funzioni PostgreSQL.
#### Motivazioni della Scelta
**Coerenza Architetturale**: Il sistema è progettato attorno a FastAPI come orchestratore centrale. Mantenere la logica di business nell'API garantisce un'architettura coerente e predicibile.
**Manutenibilità e Testabilità**: Le funzioni Python sono intrinsecamente più facili da testare, debuggare e modificare rispetto alle stored procedures. Questo si allinea con l'approccio DevOps moderno e l'integrazione continua.
**Flessibilità di Sviluppo**: La gestione della disponibilità, dei limiti di prenotazione e delle validazioni può evolvere rapidamente senza modifiche al schema database.
#### Implementazione delle Verifiche di Disponibilità
Le operazioni critiche come la verifica di disponibilità posti in un turno o di una pietanza vengono gestite tramite:
- **Query atomiche** per il recupero dati
- **Validazioni Python** per la logica di business
- **Transazioni SQLAlchemy** per garantire consistenza
- **Pattern async/await** per performance ottimali

7
requirements.txt

@ -0,0 +1,7 @@
fastapi>=0.104.0
uvicorn[standard]>=0.24.0
sqlalchemy>=2.0.0
psycopg2-binary>=2.9.0
pydantic>=2.0.0
python-jose[cryptography]>=3.3.0
python-multipart>=0.0.6

11
schema.sql

@ -2,10 +2,6 @@ CREATE TABLE pietanze (
id SERIAL PRIMARY KEY,
nome VARCHAR(150) NOT NULL,
descrizione TEXT,
categoria VARCHAR(50), -- primo, secondo, contorno, dolce
prezzo DECIMAL(5,2),
disponibile BOOLEAN DEFAULT true,
ingredienti TEXT, -- Testo libero
allergeni JSONB, -- Array di allergeni: ["glutine", "lattosio", ...]
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
@ -14,9 +10,9 @@ CREATE TABLE pietanze (
CREATE TABLE pasti (
id SERIAL PRIMARY KEY,
data_pasto DATE NOT NULL,
tipo_pasto VARCHAR(20) NOT NULL, -- colazione, pranzo, cena
portate JSONB, -- Lista di portate e relative pietanze con numero di prenotazioni massime (se 0 nessun limite): {"primo": {1: 100, 2: 50}, "secondo": {3: 100, 4: 50}, ...}
disponibile BOOLEAN DEFAULT true,
turno VARCHAR(20) NOT NULL,
turni JSONB, -- Dizionario con i turni di prenotazione e posti massimi disponibili (se 0 nessun limite): {"12:45": 100, "13:00": 100, ...}
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(data_pasto, tipo_pasto)
@ -26,8 +22,9 @@ CREATE TABLE prenotazioni (
id SERIAL PRIMARY KEY,
user_id VARCHAR(100) NOT NULL, -- Estratto dal JWT
pasto_id INTEGER REFERENCES pasti(id) ON DELETE CASCADE,
pietanze_selezionate JSONB, -- Lista di pietanze
pietanze_selezionate JSONB, -- Lista di pietanze scelte per il pasto: [1, 2, 3]
note TEXT,
stato VARCHAR(20) DEFAULT 'attiva', -- Stati: 'attiva', 'servita', 'pagata', 'annullata'
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(user_id, pasto_id)

Loading…
Cancel
Save