No description
  • Python 93.3%
  • Shell 4.7%
  • Dockerfile 2%
Find a file
2026-06-10 17:00:56 +02:00
data chore: scaffolding progetto, tooling e config di esempio 2026-06-10 11:02:44 +02:00
docs/superpowers docs: aggiunto progetto docs, prompt e claude.md 2026-06-10 12:12:44 +02:00
tests script di validazione per cambio formatori 2026-06-10 16:48:25 +02:00
.dockerignore build: Dockerfile Streamlit + dockerignore per deploy GCF 2026-06-10 11:05:37 +02:00
.gitignore script di validazione per cambio formatori 2026-06-10 16:48:25 +02:00
app.py feat: bottone Conferma verde + scenario test slot pieno da 2 posti 2026-06-10 12:12:41 +02:00
CLAUDE.md docs: deploy in produzione su marte/fwrz + gotcha WebSocket nginx 2026-06-10 12:55:46 +02:00
compose.yml build: compose.yml per deploy GCF (marte) + ignora .env 2026-06-10 15:44:49 +02:00
config.py feat: caricamento e validazione config invitati/slot 2026-06-10 11:03:07 +02:00
disponibilita.md script di validazione per cambio formatori 2026-06-10 16:48:25 +02:00
Dockerfile build: Dockerfile Streamlit + dockerignore per deploy GCF 2026-06-10 11:05:37 +02:00
export_report.py feat: export report (build_rows, CSV, riepilogo, CLI) 2026-06-10 11:03:35 +02:00
local_start.sh fix: local_start.sh rimuove container precedente anche se stoppato 2026-06-10 11:31:25 +02:00
prompt.md docs: aggiunto progetto docs, prompt e claude.md 2026-06-10 12:12:44 +02:00
pyproject.toml chore: scaffolding progetto, tooling e config di esempio 2026-06-10 11:02:44 +02:00
README.md docs: README con flusso aggiornamento slot.json in produzione via validate_slot_change.py 2026-06-10 17:00:56 +02:00
slot.md feat: slot.json da disponibilita.md + riepilogo slot.md con formatori per slot 2026-06-10 16:26:58 +02:00
slots.py feat: parsing e formattazione chiavi slot 2026-06-10 11:02:55 +02:00
store.py fix: usa timezone.utc compatibile + test regression per datetime.UTC 2026-06-10 11:24:24 +02:00
validate_slot_change.py script di validazione per cambio formatori 2026-06-10 16:48:25 +02:00

Prenotazione sessioni di inserimento assistito

App Streamlit + SQLite per prenotare gli slot di inserimento assistito (1112 giugno 2026).

Configurazione

Due file JSON in data/ (montati come volume /data nel container):

  • invitati.json — chi può prenotare. Email → nominativo:
    { "mario.rossi@gcf.it": {"nome": "Mario", "cognome": "Rossi"} }
    
  • slot.json — capienza per slot (= numero assistenti). La chiave definisce data/ora nel formato YYYYMMDDHHH:MM, es. 20260611H15:00. È questo file a stabilire quali slot esistono:
    { "20260611H15:00": 3, "20260611H15:30": 2 }
    

Partire dagli esempi: cp data/invitati.example.json data/invitati.json e cp data/slot.example.json data/slot.json.

Avvio in locale

python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
EXPORT_TOKEN=<segreto> .venv/bin/streamlit run app.py

Variabili d'ambiente: INVITATI_PATH, SLOT_PATH, DB_PATH, EXPORT_TOKEN.

Report

Due modi per ottenere il report (chi ha prenotato cosa + posti liberi):

  1. URL nascosto — visitare https://<host>/?export=<EXPORT_TOKEN>. Mostra la tabella prenotazioni con download CSV e il riepilogo per slot. Senza il token corretto la sezione non compare.
  2. CLIpython export_report.py --db <db> --slot <slot.json> --out report.csv (dentro il container: docker exec <container> python export_report.py ...).

Il file SQLite è comunque sul volume in DB_PATH.

Docker

Build e deploy seguono le procedure dell'infrastruttura GCF (skill gcf-docker-build e gcf-docker-deploy). Il container espone la porta 8501 e usa il volume /data per config, DB e CSV.

docker build -t sondaggio:dev .
docker run --rm -p 8501:8501 \
  -e EXPORT_TOKEN=segreto123 \
  -v "$PWD/data:/data" \
  sondaggio:dev

Produzione

Online su https://sondaggio.gcf-cloud.it (TLS Let's Encrypt via edge nginx su fwrz → backend marte:8006). Lo stack vive in /docker/sondaggio/ su marte (compose.yml + .env con EXPORT_TOKEN, mode 0600). data/ è di proprietà uid 1000 per consentire al container la scrittura di prenotazioni.sqlite.

Aggiornare a una nuova versione:

# build + push dalla workstation (marte non raggiunge la SSH del registry)
docker build --platform linux/amd64 \
  -t git.gcf-cloud.it/gcf_rd/sondaggio:<ver> -t git.gcf-cloud.it/gcf_rd/sondaggio:latest .
docker push git.gcf-cloud.it/gcf_rd/sondaggio:<ver>
docker push git.gcf-cloud.it/gcf_rd/sondaggio:latest
# poi su marte (sudo): allinea l'image tag in compose.yml e
docker compose -f /docker/sondaggio/compose.yml up -d

Sostituire la lista invitati: rimpiazzare /docker/sondaggio/data/invitati.json e riavviare lo stack. La griglia slot di produzione coincide con data/slot.example.json.

Nota nginx: il vhost richiede gli header WebSocket (Upgrade/Connection, proxy_http_version 1.1) per /_stcore/stream, altrimenti la UI Streamlit resta su "Connecting". Il playbook generico setup-nginx-reverseproxy.yml non li include e sovrascrive il vhost a ogni run: dopo averlo rieseguito, reiniettare gli header.

Aggiornare slot.json in produzione

Quando i formatori cambiano disponibilità, aggiornare slot.json richiede attenzione: non si può ridurre o rimuovere uno slot che ha già prenotazioni senza prima gestire gli utenti coinvolti.

Lo script validate_slot_change.py (standalone, nessuna dipendenza da Streamlit) valida il cambio prima di applicarlo.

Flusso di lavoro

  1. Copia file da marte in locale:

    scp marte:/docker/sondaggio/data/prenotazioni.sqlite ./data/
    scp marte:/docker/sondaggio/data/slot.json      ./data/
    scp marte:/docker/sondaggio/data/invitati.json    ./data/
    
  2. Crea data/slot.new.json con le nuove disponibilità.

  3. Lancia la validazione:

    python validate_slot_change.py \
      --db data/prenotazioni.sqlite \
      --slot data/slot.json \
      --new-slot data/slot.new.json \
      --invitati data/invitati.json \
      --out report.csv
    

    Exit code:

    • 0 — Nessun conflitto. Sicuro aggiornare.
    • 1 — Ci sono conflitti. Non aggiornare finché non risolti.
  4. Se OK (exit code 0):

    scp data/slot.new.json marte:/docker/sondaggio/data/slot.json
    ssh marte "docker restart sondaggio"
    
  5. Se KO (exit code 1): apri report.csv — per ogni slot conflitto trovi:

    • tipo (rimosso / ridotto)
    • capienza vecchia / nuova
    • prenotati / in eccesso
    • email e nominativo degli utenti da contattare

    Gestisci manualmente (annulla / sposta le prenotazioni in eccesso) e ripeti la validazione.


Test e qualità

.venv/bin/pytest        # test
.venv/bin/ruff check .  # lint
.venv/bin/mypy .        # type check

Supporto

Fabio Angelone — helpdesk@gcf.it · Ludovica Roncella — hr@gcf.it / l.roncella@gcf.it