longevity: giornale di bordo per cliente #16

Closed
opened 2026-09-27 19:55:59 +00:00 by Adriano · 5 comments
Owner

COSA: giornale di bordo per ogni cliente: note datate del trainer, voce più recente in alto, con autore.
PERCHÉ: richiesta di Adriano 27/09; Nicola in call (min 53): note libere ai follow-up, es. «dopo sei mesi lo stress è diminuito, ha cominciato a dimagrire e ha smesso di fumare»; obiettivi che cambiano.
DOVE: scheda cliente del gestionale (pages/longevity/gestionale/cliente/[code].astro). Dati sanitari: le note stanno in longevity.db legate al client_code, non in identity.db (stessa separazione di profilo_note).
DA DECIDERE: se il cliente vede le note (proposta: no, solo staff); se entrano voci automatiche (check-up salvato, misura corretta, cambio test).
FATTO QUANDO: il trainer aggiunge e legge note datate nella scheda; test su inserimento, ordine e accesso solo staff.
FONTE: call Adriano–Nicola 27/09/2026, trascrizione in wasabi:adp-work/AI-OS/projects/azienda/clienti/Insanity_Lab/Longevity_Project/docs/2026-09-27_call/

COSA: giornale di bordo per ogni cliente: note datate del trainer, voce più recente in alto, con autore. PERCHÉ: richiesta di Adriano 27/09; Nicola in call (min 53): note libere ai follow-up, es. «dopo sei mesi lo stress è diminuito, ha cominciato a dimagrire e ha smesso di fumare»; obiettivi che cambiano. DOVE: scheda cliente del gestionale (pages/longevity/gestionale/cliente/[code].astro). Dati sanitari: le note stanno in longevity.db legate al client_code, non in identity.db (stessa separazione di profilo_note). DA DECIDERE: se il cliente vede le note (proposta: no, solo staff); se entrano voci automatiche (check-up salvato, misura corretta, cambio test). FATTO QUANDO: il trainer aggiunge e legge note datate nella scheda; test su inserimento, ordine e accesso solo staff. FONTE: call Adriano–Nicola 27/09/2026, trascrizione in wasabi:adp-work/AI-OS/projects/azienda/clienti/Insanity_Lab/Longevity_Project/docs/2026-09-27_call/
Adriano added the sviluppo label 2026-09-27 19:55:59 +00:00
Author
Owner

DECISIONE (Adriano, 27/09/2026): il giornale di bordo è solo staff, il cliente non lo vede.

DECISIONE (Adriano, 27/09/2026): il giornale di bordo è solo staff, il cliente non lo vede.
Adriano added the assegnata:daitarn label 2026-09-27 20:20:56 +00:00
Author
Owner

🔵 daitarn — preso in carico 2026-09-27T20:20:55Z
ramo: lavoro/daitarn · capacità: build-windows, gpu

🔵 daitarn — **preso in carico** 2026-09-27T20:20:55Z ramo: `lavoro/daitarn` · capacità: build-windows, gpu
Author
Owner

ANALISI (passo 1, Opus) — gitea:Adriano/InsanityLab-web#16
RAMO: lavoro/daitarn allineato a origin/main 6bbfcd8. Cartella: apps/platforms.
DECISIONI: solo staff (Adriano 27/09): il cliente non vede il giornale. Scelte di questa analisi (minimo che serve): nessuna voce automatica; si aggiunge e si cancella, non si modifica (una nota sbagliata si cancella e si riscrive).

MODIFICHE

  1. src/lib/longevity/db.ts — SCHEMA_LONGEVITY: nuova tabella
    CREATE TABLE IF NOT EXISTS giornale (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    client_code TEXT NOT NULL REFERENCES soggetti(client_code),
    data TEXT NOT NULL, -- AAAA-MM-GG, il giorno a cui la nota si riferisce
    autore TEXT NOT NULL, -- username dello staff loggato
    testo TEXT NOT NULL,
    created_at TEXT NOT NULL DEFAULT (datetime('now'))
    );
    • indice su (client_code, data). Nessuna modifica a migra(): una tabella nuova la crea IF NOT EXISTS anche su un longevity.db esistente (verificarlo con un test che apre un DB creato con lo schema senza la tabella, oppure spiegare nel commento perché basta). Sta in longevity.db (dati sanitari, solo client_code), mai in identity.db.
  2. Nuovo src/lib/longevity/giornale.ts (stesso vincolo di gestionale.ts: solo database clinico, nessun nome; niente parole vietate da tests/longevity/anagrafica.test.ts):
    • vociDelGiornale(db, clientCode) → [{ id, data, autore, testo, created_at }] ordine data DESC, id DESC.
    • aggiungiVoce(db, { clientCode, data, autore, testo }) → { ok: true, id } | { ok: false, errore }. Rifiuta: testo vuoto dopo trim, testo > 5000 caratteri, data non AAAA-MM-GG o nel futuro, client_code senza soggetto in longevity.
    • cancellaVoce(db, { id, utente, ruolo }) → { ok, clientCode } | { ok: false, errore }. Può cancellare l'autore della voce o un admin; altrimenti errore. Voce inesistente → errore.
  3. Nuova API src/pages/api/longevity/gestionale/giornale.ts (POST, form): campo azione = aggiungi | cancella. Autore e ruolo SEMPRE da locals.user, mai dal form. Per cancella il client_code del redirect si legge dalla voce nel DB (stesso principio di verifica.ts). Redirect 303 alla scheda cliente con ?giornale=aggiunta|cancellata o ?errore=..., ancora #giornale. Rotta già riservata ad admin+trainer da src/lib/auth.ts:75.
  4. src/pages/longevity/gestionale/cliente/[code].astro: sezione «Giornale di bordo» (id="giornale") dopo Anagrafica: form con data (default oggi, max oggi) e textarea, pulsante «Aggiungi nota»; sotto l'elenco delle voci (data, autore, testo con a capo preservati), pulsante «Cancella» solo se utente = autore o ruolo admin. Messaggi per ?giornale=. Nei form niente (tests/longevity/referto.test.ts intercetta la parola). Il cliente: nessuna pagina sotto /longevity/io, /longevity/progressione, /longevity/questionario deve leggere giornale.ts — aggiungere un test che lo verifica sul testo dei file (stile anagrafica.test.ts). TEST (tests/longevity/giornale.test.ts, DB in memoria o stesso schema di pulizia di verifica-misure.test.ts) aggiunta e lettura, ordine data DESC poi id DESC; a capo conservati. rifiuti di aggiungiVoce: testo vuoto/spazi, troppo lungo, data futura, data malformata, cliente inesistente — nessuna riga scritta. cancellaVoce: autore sì, admin sì, altro trainer no, id inesistente no. schema: la tabella si crea su un longevity.db preesistente senza tabella giornale. nessuna pagina cliente importa giornale. NON TOCCARE: motore, registro, misure/sessioni/score, questionario, anagrafica e identity, migra() (salvo che il test dello schema dimostri che serve), pagine cliente. PROVA: in apps/platforms npx vitest run (baseline Windows: 264 verdi, 4 rossi di piattaforma: campus-lib resolveAsset; anagrafica.test.ts separatori \; EPERM in gestionale.test.ts e questionario-pagina.test.ts — nessun rosso nuovo), npx tsc --noEmit, npm run build.
ANALISI (passo 1, Opus) — gitea:Adriano/InsanityLab-web#16 RAMO: lavoro/daitarn allineato a origin/main 6bbfcd8. Cartella: apps/platforms. DECISIONI: solo staff (Adriano 27/09): il cliente non vede il giornale. Scelte di questa analisi (minimo che serve): nessuna voce automatica; si aggiunge e si cancella, non si modifica (una nota sbagliata si cancella e si riscrive). MODIFICHE 1. src/lib/longevity/db.ts — SCHEMA_LONGEVITY: nuova tabella CREATE TABLE IF NOT EXISTS giornale ( id INTEGER PRIMARY KEY AUTOINCREMENT, client_code TEXT NOT NULL REFERENCES soggetti(client_code), data TEXT NOT NULL, -- AAAA-MM-GG, il giorno a cui la nota si riferisce autore TEXT NOT NULL, -- username dello staff loggato testo TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT (datetime('now')) ); + indice su (client_code, data). Nessuna modifica a migra(): una tabella nuova la crea IF NOT EXISTS anche su un longevity.db esistente (verificarlo con un test che apre un DB creato con lo schema senza la tabella, oppure spiegare nel commento perché basta). Sta in longevity.db (dati sanitari, solo client_code), mai in identity.db. 2. Nuovo src/lib/longevity/giornale.ts (stesso vincolo di gestionale.ts: solo database clinico, nessun nome; niente parole vietate da tests/longevity/anagrafica.test.ts): - `vociDelGiornale(db, clientCode)` → [{ id, data, autore, testo, created_at }] ordine data DESC, id DESC. - `aggiungiVoce(db, { clientCode, data, autore, testo })` → { ok: true, id } | { ok: false, errore }. Rifiuta: testo vuoto dopo trim, testo > 5000 caratteri, data non AAAA-MM-GG o nel futuro, client_code senza soggetto in longevity. - `cancellaVoce(db, { id, utente, ruolo })` → { ok, clientCode } | { ok: false, errore }. Può cancellare l'autore della voce o un admin; altrimenti errore. Voce inesistente → errore. 3. Nuova API src/pages/api/longevity/gestionale/giornale.ts (POST, form): campo `azione` = aggiungi | cancella. Autore e ruolo SEMPRE da locals.user, mai dal form. Per cancella il client_code del redirect si legge dalla voce nel DB (stesso principio di verifica.ts). Redirect 303 alla scheda cliente con `?giornale=aggiunta|cancellata` o `?errore=...`, ancora `#giornale`. Rotta già riservata ad admin+trainer da src/lib/auth.ts:75. 4. src/pages/longevity/gestionale/cliente/[code].astro: sezione «Giornale di bordo» (id="giornale") dopo Anagrafica: form con data (default oggi, max oggi) e textarea, pulsante «Aggiungi nota»; sotto l'elenco delle voci (data, autore, testo con a capo preservati), pulsante «Cancella» solo se utente = autore o ruolo admin. Messaggi per `?giornale=`. Nei form niente <select> (tests/longevity/referto.test.ts intercetta la parola). Il cliente: nessuna pagina sotto /longevity/io, /longevity/progressione, /longevity/questionario deve leggere giornale.ts — aggiungere un test che lo verifica sul testo dei file (stile anagrafica.test.ts). TEST (tests/longevity/giornale.test.ts, DB in memoria o stesso schema di pulizia di verifica-misure.test.ts) - aggiunta e lettura, ordine data DESC poi id DESC; a capo conservati. - rifiuti di aggiungiVoce: testo vuoto/spazi, troppo lungo, data futura, data malformata, cliente inesistente — nessuna riga scritta. - cancellaVoce: autore sì, admin sì, altro trainer no, id inesistente no. - schema: la tabella si crea su un longevity.db preesistente senza tabella giornale. - nessuna pagina cliente importa giornale. NON TOCCARE: motore, registro, misure/sessioni/score, questionario, anagrafica e identity, migra() (salvo che il test dello schema dimostri che serve), pagine cliente. PROVA: in apps/platforms `npx vitest run` (baseline Windows: 264 verdi, 4 rossi di piattaforma: campus-lib resolveAsset; anagrafica.test.ts separatori `\`; EPERM in gestionale.test.ts e questionario-pagina.test.ts — nessun rosso nuovo), `npx tsc --noEmit`, `npm run build`.
Author
Owner

ESITO: fatto sul ramo, non in main né in produzione
RIF: gitea:Adriano/InsanityLab-web#16
COSA: controllo finale (passo 3, Opus): il diff fa quello che dice l'analisi e solo quello.
COMMIT (lavoro/daitarn): 00ecfe8 schema+libreria, 37b1a31 test, cef08aa API, 2231a47 sezione nella scheda cliente.
PROVA: apps/platforms npx vitest run → 277 verdi, 4 rossi = baseline Windows (anagrafica.test.ts segnala solo anagrafica.ts e db.ts); tsc 0; build ok.
NOTA: 'oggi' è la data UTC del server (come già nel check-up): fra mezzanotte e le 02:00 ora italiana la data di oggi risulta futura. Non corretto qui, vale per tutto il gestionale.
MANCA: via di Adriano per merge e deploy (tabella nuova creata da CREATE TABLE IF NOT EXISTS all'apertura, backup prima).

ESITO: fatto sul ramo, non in main né in produzione RIF: gitea:Adriano/InsanityLab-web#16 COSA: controllo finale (passo 3, Opus): il diff fa quello che dice l'analisi e solo quello. COMMIT (lavoro/daitarn): 00ecfe8 schema+libreria, 37b1a31 test, cef08aa API, 2231a47 sezione nella scheda cliente. PROVA: apps/platforms npx vitest run → 277 verdi, 4 rossi = baseline Windows (anagrafica.test.ts segnala solo anagrafica.ts e db.ts); tsc 0; build ok. NOTA: 'oggi' è la data UTC del server (come già nel check-up): fra mezzanotte e le 02:00 ora italiana la data di oggi risulta futura. Non corretto qui, vale per tutto il gestionale. MANCA: via di Adriano per merge e deploy (tabella nuova creata da CREATE TABLE IF NOT EXISTS all'apertura, backup prima).
Author
Owner

Soluzione

ESITO: fatto, in produzione
RIF: gitea:Adriano/InsanityLab-web#16
COSA: sezione «Giornale di bordo» nella scheda cliente del gestionale: note datate con autore, più recente in alto; aggiunta da trainer/admin; cancellazione solo autore o admin; nessuna modifica, nessuna voce automatica; solo staff.
FILE: apps/platforms/src/lib/longevity/db.ts (tabella giornale + indice), src/lib/longevity/giornale.ts (vociDelGiornale, aggiungiVoce, cancellaVoce), src/pages/api/longevity/gestionale/giornale.ts, src/pages/longevity/gestionale/cliente/[code].astro; tests/longevity/giornale.test.ts (13 test, incluso: nessuna pagina cliente importa giornale.ts).
COMMIT: 00ecfe8 37b1a31 cef08aa 2231a47 — main 2231a47.
DEPLOY: 27/09/2026 20:26 UTC. Backup prima: /opt/docker/insanitylab-platforms/backup/20260927T202609Z-pre-16/ (3 DB, integrity ok).
PROVA: vitest 277 verdi + 4 rossi baseline Windows; tsc 0; build ok; in produzione apertura di longevity.db dal chunk db_Sh0aJSGM.mjs → tabelle giornale e idx_giornale_cliente presenti, 0 voci, 10 soggetti intatti.
NON VERIFICATO: prova da browser loggato.
LIMITE NOTO: 'oggi' in UTC (vale per tutto il gestionale).

**Soluzione** ESITO: fatto, in produzione RIF: gitea:Adriano/InsanityLab-web#16 COSA: sezione «Giornale di bordo» nella scheda cliente del gestionale: note datate con autore, più recente in alto; aggiunta da trainer/admin; cancellazione solo autore o admin; nessuna modifica, nessuna voce automatica; solo staff. FILE: apps/platforms/src/lib/longevity/db.ts (tabella giornale + indice), src/lib/longevity/giornale.ts (vociDelGiornale, aggiungiVoce, cancellaVoce), src/pages/api/longevity/gestionale/giornale.ts, src/pages/longevity/gestionale/cliente/[code].astro; tests/longevity/giornale.test.ts (13 test, incluso: nessuna pagina cliente importa giornale.ts). COMMIT: 00ecfe8 37b1a31 cef08aa 2231a47 — main 2231a47. DEPLOY: 27/09/2026 20:26 UTC. Backup prima: /opt/docker/insanitylab-platforms/backup/20260927T202609Z-pre-16/ (3 DB, integrity ok). PROVA: vitest 277 verdi + 4 rossi baseline Windows; tsc 0; build ok; in produzione apertura di longevity.db dal chunk db_Sh0aJSGM.mjs → tabelle giornale e idx_giornale_cliente presenti, 0 voci, 10 soggetti intatti. NON VERIFICATO: prova da browser loggato. LIMITE NOTO: 'oggi' in UTC (vale per tutto il gestionale).
Adriano removed the assegnata:daitarn label 2026-09-27 20:26:47 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Adriano/InsanityLab-web#16