longevity: misureValideAlla, spareggio sulla riga e nota sulla conferma dei fuori range
Refs #1 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -144,15 +144,21 @@ export const FINESTRA_GIORNI: number | null = null;
|
|||||||
* questionario del giorno D, e viceversa una sessione del giorno D-1 non vede nulla di ciò
|
* questionario del giorno D, e viceversa una sessione del giorno D-1 non vede nulla di ciò
|
||||||
* che accadrà dopo di lei.
|
* che accadrà dopo di lei.
|
||||||
*
|
*
|
||||||
* "Più recente" = data della sessione DESC, poi id DESC (a parità di data, l'inserimento
|
* "Più recente" = data della sessione DESC, poi id di sessione DESC (a parità di data,
|
||||||
* più tardo vince) — stesso criterio di `leggiScore`. A parità di sessione (una misura
|
* l'inserimento più tardo vince) — stesso criterio di `leggiScore`. A parità di SESSIONE
|
||||||
* ri-registrata più volte nella stessa sessione, oggi non capita ma non è vietato) vince
|
* (due misure dello stesso test_id nella stessa sessione: `registraMisure` non lo vieta,
|
||||||
* comunque la più recente per `id` di riga in `misure`, perché la query è ordinata anche
|
* es. una correzione manuale dopo un refuso) l'ORDER BY aggiunge un terzo criterio
|
||||||
* su quello implicitamente tramite l'ordine della sessione.
|
* esplicito, `m.id` di riga in `misure` DESC: vince quella scritta dopo. Senza questo
|
||||||
|
* terzo criterio le due righe uscirebbero in un ordine NON definito da SQL (nessuna delle
|
||||||
|
* due chiavi precedenti le distingue), non "implicito" come diceva una versione precedente
|
||||||
|
* di questo commento — un ordine che sembra stabile per come SQLite le restituisce oggi,
|
||||||
|
* ma su cui non si può contare.
|
||||||
*
|
*
|
||||||
* Stessa esclusione di `fuori_range = 1` che c'era prima nella lettura diretta (§9 della
|
* Stessa esclusione di `fuori_range = 1` che c'era prima nella lettura diretta (§9 della
|
||||||
* spec): una misura fuori dal range dichiarato non entra, né dalla sessione corrente né da
|
* spec): una misura fuori dal range dichiarato non entra, né dalla sessione corrente né da
|
||||||
* una precedente.
|
* una precedente. La colonna della conferma non esiste ancora (§12 della spec, issue #7):
|
||||||
|
* quando ci sarà, questo filtro andrà rilassato per lasciar passare le misure confermate,
|
||||||
|
* non tolto del tutto.
|
||||||
*/
|
*/
|
||||||
export function misureValideAlla(db: Database.Database, sessioneId: number): Map<string, number> {
|
export function misureValideAlla(db: Database.Database, sessioneId: number): Map<string, number> {
|
||||||
const sessione = db.prepare(
|
const sessione = db.prepare(
|
||||||
@@ -166,13 +172,16 @@ export function misureValideAlla(db: Database.Database, sessioneId: number): Map
|
|||||||
JOIN sessioni s2 ON s2.id = m.sessione_id
|
JOIN sessioni s2 ON s2.id = m.sessione_id
|
||||||
WHERE m.client_code = ? AND m.fuori_range = 0 AND m.valore_num IS NOT NULL
|
WHERE m.client_code = ? AND m.fuori_range = 0 AND m.valore_num IS NOT NULL
|
||||||
AND (s2.data < ? OR (s2.data = ? AND s2.id <= ?))
|
AND (s2.data < ? OR (s2.data = ? AND s2.id <= ?))
|
||||||
ORDER BY s2.data DESC, s2.id DESC`
|
ORDER BY s2.data DESC, s2.id DESC, m.id DESC`
|
||||||
).all(sessione.client_code, sessione.data, sessione.data, sessione.id) as
|
).all(sessione.client_code, sessione.data, sessione.data, sessione.id) as
|
||||||
{ test_id: string; valore_num: number; data: string }[];
|
{ test_id: string; valore_num: number; data: string }[];
|
||||||
|
|
||||||
const mappa = new Map<string, number>();
|
const mappa = new Map<string, number>();
|
||||||
for (const r of righe) {
|
for (const r of righe) {
|
||||||
if (mappa.has(r.test_id)) continue; // gia' trovato un valore piu' recente per questo test_id
|
// gia' trovato un valore per questo test_id: e' il piu' recente, per data di sessione,
|
||||||
|
// poi id di sessione, poi (spareggio) id di riga in misure — tutti e tre espliciti
|
||||||
|
// nell'ORDER BY qui sopra, la prima riga per test_id in questo ciclo e' sempre quella giusta.
|
||||||
|
if (mappa.has(r.test_id)) continue;
|
||||||
if (FINESTRA_GIORNI !== null) {
|
if (FINESTRA_GIORNI !== null) {
|
||||||
const giorni = (Date.parse(sessione.data) - Date.parse(r.data)) / 86_400_000;
|
const giorni = (Date.parse(sessione.data) - Date.parse(r.data)) / 86_400_000;
|
||||||
if (giorni > FINESTRA_GIORNI) continue;
|
if (giorni > FINESTRA_GIORNI) continue;
|
||||||
|
|||||||
@@ -198,6 +198,20 @@ describe('un check-up e un questionario sono sessioni separate, ma un cliente e
|
|||||||
expect(sd).not.toHaveProperty('questionario_lifestyle');
|
expect(sd).not.toHaveProperty('questionario_lifestyle');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('due misure dello stesso test_id nella stessa sessione: vince quella inserita dopo', () => {
|
||||||
|
// registraMisure non vieta di scrivere due volte lo stesso test_id nella stessa
|
||||||
|
// sessione (es. una correzione manuale dopo un refuso di battitura). data di sessione
|
||||||
|
// e id di sessione sono identici per le due righe: senza uno spareggio esplicito su
|
||||||
|
// m.id (la riga in `misure`), l'ordine fra le due sarebbe indefinito.
|
||||||
|
const db = dbPronto('ISL-0023', 'M');
|
||||||
|
const s = apriSessione(db, { client_code: 'ISL-0023', data: '2026-08-05', tipo: 'checkup', eta_alla_data: 38 });
|
||||||
|
registraMisure(db, s, 'manuale', [{ test_id: 'f_grasso_pct', valore_num: 20 }]); // scritta per prima, refuso
|
||||||
|
registraMisure(db, s, 'manuale', [{ test_id: 'f_grasso_pct', valore_num: 12.8 }]); // corretta subito dopo
|
||||||
|
|
||||||
|
const misurate = misureValideAlla(db, s);
|
||||||
|
expect(misurate.get('f_grasso_pct')).toBe(12.8); // l'ultima scritta, non la prima
|
||||||
|
});
|
||||||
|
|
||||||
it('una misura fuori range viene ignorata e sostituita dalla precedente misura valida', () => {
|
it('una misura fuori range viene ignorata e sostituita dalla precedente misura valida', () => {
|
||||||
const db = dbPronto('ISL-0022', 'M');
|
const db = dbPronto('ISL-0022', 'M');
|
||||||
const s1 = apriSessione(db, { client_code: 'ISL-0022', data: '2026-08-05', tipo: 'checkup', eta_alla_data: 38 });
|
const s1 = apriSessione(db, { client_code: 'ISL-0022', data: '2026-08-05', tipo: 'checkup', eta_alla_data: 38 });
|
||||||
|
|||||||
Reference in New Issue
Block a user