longevity: conferma delle misure fuori range dal gestionale #7

Closed
opened 2026-09-26 12:22:14 +00:00 by Adriano · 6 comments
Owner

COSA: spec §9: le misure con fuori_range=1 non entrano nello score finché qualcuno non le conferma. La colonna di conferma non esiste; calcolaSessione (motore/index.ts) le esclude sempre.
FATTO QUANDO: il trainer conferma o scarta una misura marcata; la conferma ricalcola la sessione; test.

COSA: spec §9: le misure con fuori_range=1 non entrano nello score finché qualcuno non le conferma. La colonna di conferma non esiste; calcolaSessione (motore/index.ts) le esclude sempre. FATTO QUANDO: il trainer conferma o scarta una misura marcata; la conferma ricalcola la sessione; test.
Adriano added the sviluppo label 2026-09-26 12:22:14 +00:00
Adriano added the assegnata:goldrake label 2026-09-26 12:53:29 +00:00
Author
Owner

🤖 goldrake — preso in carico 2026-09-26T12:53:29Z
ramo: lavoro/goldrake · capacità: docker, pubblica, sempre-accesa, systemd

🤖 goldrake — **preso in carico** 2026-09-26T12:53:29Z ramo: `lavoro/goldrake` · capacità: docker, pubblica, sempre-accesa, systemd
Author
Owner

ESITO: richiesta
RIF: gitea:Adriano/InsanityLab-web#7
COSA: analisi (passo 1). Verifica delle misure fuori range: confermata (entra nello score) o scartata; migrazione dello schema; ricalcolo. Parte libreria + API; il pulsante nella scheda cliente arriva con le pagine del gestionale (#2).
RAMO: lavoro/goldrake-i7 — worktree goldrake:~/lavoro/InsanityLab-web-i7 da af8afeb.

Stato verificato

  • misure.fuori_range (lib/longevity/db.ts) marcato da registraMisure (misure.ts); misureValideAlla (motore/index.ts) filtra fuori_range = 0; commento lì rimanda a questa issue.
  • In produzione esiste già un longevity.db (VPS: /opt/docker/insanitylab-apps/apps/platforms/data/longevity.db): CREATE TABLE IF NOT EXISTS non aggiunge colonne a una tabella esistente → serve una migrazione vera (commento su score in db.ts descrive la stessa trappola).
  • leggiScore legge per ogni elemento la riga con MAX(id) della sessione: un ricalcolo che aggiunge righe a score sostituisce il referto senza cancellare la storia.

Modifiche

  1. db.ts: in SCHEMA_LONGEVITY, tabella misure, tre colonne: verifica TEXT CHECK (verifica IN ('confermata','scartata')), verificata_da TEXT, verificata_at TEXT. Nuova funzione privata migra(db) chiamata in createLongevityDb dopo lo schema: PRAGMA table_info(misure), ALTER TABLE misure ADD COLUMN ... per ogni colonna assente. Idempotente. Commento: perché serve (il DB di produzione esiste dal 03/09).
  2. motore/index.ts misureValideAlla: filtro (m.fuori_range = 0 OR m.verifica = 'confermata'); aggiornare il commento (la conferma ora esiste).
  3. misure.ts:
    • misureDaVerificare(db, clientCode): fuori_range = 1 AND verifica IS NULL, con id, test_id, etichetta dal registro, valore_num, unita, range min/max, data della sessione; ordine data DESC.
    • verificaMisura(db, { misuraId, esito: 'confermata'|'scartata', operatore }) → { ok: true; sessioniRicalcolate: number[] } | { ok: false; errore }. Rifiuta: misura inesistente, fuori_range = 0, già verificata. Transazione: UPDATE (esito, operatore, datetime('now')); solo se confermata: salvaScore(db, id, calcolaSessione(db, id)) per la sessione della misura e per ogni sessione successiva dello stesso cliente (data > D OR (data = D AND id > S)), perché anche quelle ereditano la misura tramite misureValideAlla. scartata non ricalcola niente.
  4. Nuovo pages/api/longevity/gestionale/verifica.ts POST (form): misura_id, esito. operatore = locals.user.username. Il codice cliente del redirect si legge dal DB (la misura), mai dal corpo. Esito: 303 a /longevity/gestionale/cliente/<code>?verificata=<esito>; errore: 303 alla stessa pagina con ?errore=<testo>; misura inesistente: 404 JSON.

TEST (tests/longevity/verifica-misure.test.ts)

  • migrazione: file temporaneo con la tabella misure vecchia (senza le tre colonne) e una riga → createLongevityDb(path) → colonne presenti, riga intatta; seconda apertura senza errori.
  • misura fuori range confermata → entra nello score: leggiScore della sua sessione cambia; una sessione successiva senza quel test ne eredita il valore e viene ricalcolata; sessioniRicalcolate le elenca.
  • scartata → resta esclusa, nessuna riga nuova in score.
  • doppia verifica, misura nel range, id inesistente → ok:false, nessuna scrittura.
  • canAccessPath('cliente', '/api/longevity/gestionale/verifica') false; trainer true.
  • Tutti i test esistenti verdi (212); tsc 0 errori.

NON TOCCARE

anagrafica.ts, auth.ts, registro.ts, motore/fisici.ts, pagine .astro, lib/longevity/gestionale.ts (lo sta scrivendo un altro agente su un altro ramo), apps/sito/.

ESITO: richiesta RIF: gitea:Adriano/InsanityLab-web#7 COSA: analisi (passo 1). Verifica delle misure fuori range: confermata (entra nello score) o scartata; migrazione dello schema; ricalcolo. Parte libreria + API; il pulsante nella scheda cliente arriva con le pagine del gestionale (#2). RAMO: lavoro/goldrake-i7 — worktree goldrake:~/lavoro/InsanityLab-web-i7 da af8afeb. ## Stato verificato - `misure.fuori_range` (lib/longevity/db.ts) marcato da `registraMisure` (misure.ts); `misureValideAlla` (motore/index.ts) filtra `fuori_range = 0`; commento lì rimanda a questa issue. - **In produzione esiste già un longevity.db** (VPS: /opt/docker/insanitylab-apps/apps/platforms/data/longevity.db): `CREATE TABLE IF NOT EXISTS` non aggiunge colonne a una tabella esistente → serve una migrazione vera (commento su `score` in db.ts descrive la stessa trappola). - `leggiScore` legge per ogni elemento la riga con MAX(id) della sessione: un ricalcolo che **aggiunge** righe a `score` sostituisce il referto senza cancellare la storia. ## Modifiche 1. `db.ts`: in `SCHEMA_LONGEVITY`, tabella `misure`, tre colonne: `verifica TEXT CHECK (verifica IN ('confermata','scartata'))`, `verificata_da TEXT`, `verificata_at TEXT`. Nuova funzione privata `migra(db)` chiamata in `createLongevityDb` dopo lo schema: `PRAGMA table_info(misure)`, `ALTER TABLE misure ADD COLUMN ...` per ogni colonna assente. Idempotente. Commento: perché serve (il DB di produzione esiste dal 03/09). 2. `motore/index.ts` `misureValideAlla`: filtro `(m.fuori_range = 0 OR m.verifica = 'confermata')`; aggiornare il commento (la conferma ora esiste). 3. `misure.ts`: - `misureDaVerificare(db, clientCode)`: `fuori_range = 1 AND verifica IS NULL`, con `id`, `test_id`, etichetta dal registro, `valore_num`, `unita`, range min/max, data della sessione; ordine data DESC. - `verificaMisura(db, { misuraId, esito: 'confermata'|'scartata', operatore })` → `{ ok: true; sessioniRicalcolate: number[] } | { ok: false; errore }`. Rifiuta: misura inesistente, `fuori_range = 0`, già verificata. Transazione: UPDATE (esito, operatore, `datetime('now')`); solo se `confermata`: `salvaScore(db, id, calcolaSessione(db, id))` per la sessione della misura e per ogni sessione successiva dello stesso cliente (`data > D OR (data = D AND id > S)`), perché anche quelle ereditano la misura tramite `misureValideAlla`. `scartata` non ricalcola niente. 4. Nuovo `pages/api/longevity/gestionale/verifica.ts` POST (form): `misura_id`, `esito`. `operatore` = `locals.user.username`. Il codice cliente del redirect si legge **dal DB** (la misura), mai dal corpo. Esito: 303 a `/longevity/gestionale/cliente/<code>?verificata=<esito>`; errore: 303 alla stessa pagina con `?errore=<testo>`; misura inesistente: 404 JSON. ## TEST (`tests/longevity/verifica-misure.test.ts`) - migrazione: file temporaneo con la tabella `misure` **vecchia** (senza le tre colonne) e una riga → `createLongevityDb(path)` → colonne presenti, riga intatta; seconda apertura senza errori. - misura fuori range confermata → entra nello score: `leggiScore` della sua sessione cambia; una sessione successiva senza quel test ne eredita il valore e viene ricalcolata; `sessioniRicalcolate` le elenca. - scartata → resta esclusa, nessuna riga nuova in `score`. - doppia verifica, misura nel range, id inesistente → `ok:false`, nessuna scrittura. - `canAccessPath('cliente', '/api/longevity/gestionale/verifica')` false; trainer true. - Tutti i test esistenti verdi (212); tsc 0 errori. ## NON TOCCARE anagrafica.ts, auth.ts, registro.ts, motore/fisici.ts, pagine `.astro`, `lib/longevity/gestionale.ts` (lo sta scrivendo un altro agente su un altro ramo), `apps/sito/`.
Author
Owner

ESITO: fatto (libreria + API), in attesa di merge
RIF: gitea:Adriano/InsanityLab-web#7
COMMIT: f096807 schema + migra() · 922ab40 verificaMisura, misureDaVerificare, POST /api/longevity/gestionale/verifica — ramo lavoro/goldrake-i7 (pushato)
PROVA: npx vitest run → 219 passed (212 + 7), migrazione provata su file temporaneo con la vecchia tabella misure; tsc 0 errori
CONTROLLO FINALE (Opus): conforme all'analisi.
MANCA: pulsanti Conferma/Scarta nella scheda cliente (pagine di #2, 2b, usano oggi misureFuoriRange: da passare a misureDaVerificare dopo il merge). Al primo avvio in produzione migra() aggiunge 3 colonne al longevity.db esistente: backup del file prima del deploy.

ESITO: fatto (libreria + API), in attesa di merge RIF: gitea:Adriano/InsanityLab-web#7 COMMIT: f096807 schema + migra() · 922ab40 verificaMisura, misureDaVerificare, POST /api/longevity/gestionale/verifica — ramo lavoro/goldrake-i7 (pushato) PROVA: npx vitest run → 219 passed (212 + 7), migrazione provata su file temporaneo con la vecchia tabella misure; tsc 0 errori CONTROLLO FINALE (Opus): conforme all'analisi. MANCA: pulsanti Conferma/Scarta nella scheda cliente (pagine di #2, 2b, usano oggi misureFuoriRange: da passare a misureDaVerificare dopo il merge). Al primo avvio in produzione migra() aggiunge 3 colonne al longevity.db esistente: backup del file prima del deploy.
Author
Owner

ESITO: richiesta
RIF: gitea:Adriano/InsanityLab-web#7, #8, #2
COSA: analisi (passo 1). Collegare alla scheda cliente del gestionale la verifica dei fuori range (#7) e la creazione dell'accesso (#8). Ramo lavoro/goldrake a 6cbb205 (merge di #5, #7, #8 sopra la 2b di #2; 257 test verdi, build ok).

Stato verificato

  • apps/platforms/src/pages/longevity/gestionale/cliente/[code].astro: sezione fuori range letta con misureFuoriRange (lib/longevity/gestionale.ts:148), senza id misura né azioni; mostra ?salvato, ?fuori, ?errore; nessun link all'accesso.
  • lib/longevity/misure.ts misureDaVerificare(db, code): stesse misure ma solo quelle non ancora verificate, con id, range_min, range_max.
  • pages/api/longevity/gestionale/verifica.ts POST form misura_id, esito (confermata|scartata) → 303 alla scheda con ?verificata=<esito> o ?errore=<testo>.
  • pages/longevity/gestionale/cliente/[code]/accesso.astro esiste (#8); nessuna pagina ci porta.
  • misureFuoriRange ha un solo chiamante (la scheda) e un test (tests/longevity/gestionale.test.ts:128-143).

Modifiche

  1. Scheda [code].astro:
    a. sezione fuori range da misureDaVerificare al posto di misureFuoriRange. Per riga: etichetta, valore + unità, range atteso «min–max», data, due form POST verso /api/longevity/gestionale/verifica con misura_id nascosto e un bottone ciascuno: «Conferma: il dato è vero» (esito=confermata) e «Scarta: è un errore» (esito=scartata). Una riga di spiegazione sopra la tabella: una misura confermata entra nei punteggi e ricalcola quella sessione e le successive; una scartata resta fuori.
    b. messaggio per ?verificata=confermata («Misura confermata: punteggi ricalcolati.») e ?verificata=scartata («Misura scartata.»).
    c. se !cliente.ha_accesso: link-bottone «Crea accesso al referto» verso /longevity/gestionale/cliente/<code>/accesso, accanto a «Nuovo check-up».
  2. lib/longevity/gestionale.ts: togliere misureFuoriRange e il suo tipo MisuraFuoriRange; il test di gestionale.test.ts che la usa passa a misureDaVerificare (stesse asserzioni sul contenuto).
  3. accesso.astro: link «Torna alla scheda» verso /longevity/gestionale/cliente/<code> in tutti gli stati della pagina.

TEST

  • tests/longevity/pagine.test.ts: la scheda contiene action="/api/longevity/gestionale/verifica", name="misura_id", entrambi gli esiti, il link /accesso; nessuna pagina contiene più misureFuoriRange.
  • npx vitest run tutto verde (partenza 257); npx tsc --noEmit -p . 0 errori; npm run build ok.

NON TOCCARE

motore, db.ts, misure.ts, anagrafica.ts, accesso.ts, le API, auth.ts, gli altri file .astro, apps/sito/. Niente parola select nelle pagine (tests/longevity/referto.test.ts la legge come SQL).

ESITO: richiesta RIF: gitea:Adriano/InsanityLab-web#7, #8, #2 COSA: analisi (passo 1). Collegare alla scheda cliente del gestionale la verifica dei fuori range (#7) e la creazione dell'accesso (#8). Ramo lavoro/goldrake a 6cbb205 (merge di #5, #7, #8 sopra la 2b di #2; 257 test verdi, build ok). ## Stato verificato - `apps/platforms/src/pages/longevity/gestionale/cliente/[code].astro`: sezione fuori range letta con `misureFuoriRange` (lib/longevity/gestionale.ts:148), senza id misura né azioni; mostra `?salvato`, `?fuori`, `?errore`; nessun link all'accesso. - `lib/longevity/misure.ts` `misureDaVerificare(db, code)`: stesse misure ma solo quelle non ancora verificate, con `id`, `range_min`, `range_max`. - `pages/api/longevity/gestionale/verifica.ts` POST form `misura_id`, `esito` (confermata|scartata) → 303 alla scheda con `?verificata=<esito>` o `?errore=<testo>`. - `pages/longevity/gestionale/cliente/[code]/accesso.astro` esiste (#8); nessuna pagina ci porta. - `misureFuoriRange` ha un solo chiamante (la scheda) e un test (tests/longevity/gestionale.test.ts:128-143). ## Modifiche 1. Scheda `[code].astro`: a. sezione fuori range da `misureDaVerificare` al posto di `misureFuoriRange`. Per riga: etichetta, valore + unità, range atteso «min–max», data, due form POST verso `/api/longevity/gestionale/verifica` con `misura_id` nascosto e un bottone ciascuno: «Conferma: il dato è vero» (`esito=confermata`) e «Scarta: è un errore» (`esito=scartata`). Una riga di spiegazione sopra la tabella: una misura confermata entra nei punteggi e ricalcola quella sessione e le successive; una scartata resta fuori. b. messaggio per `?verificata=confermata` («Misura confermata: punteggi ricalcolati.») e `?verificata=scartata` («Misura scartata.»). c. se `!cliente.ha_accesso`: link-bottone «Crea accesso al referto» verso `/longevity/gestionale/cliente/<code>/accesso`, accanto a «Nuovo check-up». 2. `lib/longevity/gestionale.ts`: togliere `misureFuoriRange` e il suo tipo `MisuraFuoriRange`; il test di gestionale.test.ts che la usa passa a `misureDaVerificare` (stesse asserzioni sul contenuto). 3. `accesso.astro`: link «Torna alla scheda» verso `/longevity/gestionale/cliente/<code>` in tutti gli stati della pagina. ## TEST - `tests/longevity/pagine.test.ts`: la scheda contiene `action="/api/longevity/gestionale/verifica"`, `name="misura_id"`, entrambi gli esiti, il link `/accesso`; nessuna pagina contiene più `misureFuoriRange`. - `npx vitest run` tutto verde (partenza 257); `npx tsc --noEmit -p .` 0 errori; `npm run build` ok. ## NON TOCCARE motore, db.ts, misure.ts, anagrafica.ts, accesso.ts, le API, auth.ts, gli altri file .astro, `apps/sito/`. Niente parola `select` nelle pagine (tests/longevity/referto.test.ts la legge come SQL).
Author
Owner

Soluzione

Verifica misure fuori range: db.ts colonne verifica/verificata_da/verificata_at con migra() idempotente all'avvio (ALTER TABLE: backup di longevity.db prima del deploy); misureValideAlla accetta fuori_range solo se confermata; misure.ts misureDaVerificare e verificaMisura (ricalcola sessione e successive); API pages/api/longevity/gestionale/verifica.ts; form Conferma/Scarta nella scheda cliente. Commit f096807, 922ab40, 2c9a74f. Stato: sul ramo lavoro/goldrake (commit 2c9a74f), NON ancora in main né in produzione. PROVA: vitest 259/259, tsc 0 errori, build ok.

**Soluzione** Verifica misure fuori range: db.ts colonne verifica/verificata_da/verificata_at con migra() idempotente all'avvio (ALTER TABLE: backup di longevity.db prima del deploy); misureValideAlla accetta fuori_range solo se confermata; misure.ts misureDaVerificare e verificaMisura (ricalcola sessione e successive); API pages/api/longevity/gestionale/verifica.ts; form Conferma/Scarta nella scheda cliente. Commit f096807, 922ab40, 2c9a74f. Stato: sul ramo lavoro/goldrake (commit 2c9a74f), NON ancora in main né in produzione. PROVA: vitest 259/259, tsc 0 errori, build ok.
Adriano removed the assegnata:goldrake label 2026-09-26 13:12:26 +00:00
Author
Owner

ESITO: fatto
COSA: in produzione su piattaforme.tielogic.xyz, 2026-09-26 13:17 UTC. main 12b2e91.
PROVA: docker compose up -d --build → container Up; migra() → colonne verifica/verificata_da/verificata_at presenti; registro_test f_ = 24; misure 20 prima e dopo.
BACKUP: /opt/docker/insanitylab-platforms/backup/*-pre-gestionale (sqlite3 .backup, integrity ok).

ESITO: fatto COSA: in produzione su piattaforme.tielogic.xyz, 2026-09-26 13:17 UTC. main 12b2e91. PROVA: docker compose up -d --build → container Up; migra() → colonne verifica/verificata_da/verificata_at presenti; registro_test f_ = 24; misure 20 prima e dopo. BACKUP: /opt/docker/insanitylab-platforms/backup/*-pre-gestionale (sqlite3 .backup, integrity ok).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Adriano/InsanityLab-web#7