Files
EVCS/tests/kilometrage/rejeu-correction.mjs

48 lines
3.9 KiB
JavaScript

// Rejoue la correction humaine du 04/10 (JEEP -> ZERO a 17:16) sur la vraie
// base, dans une transaction ANNULEE. A lancer dans le conteneur d'historisation.
import fs from 'node:fs';
import pg from 'pg';
const src = fs.readFileSync(new URL('../../tools/historise-evcs.mjs', import.meta.url), 'utf8');
const debut = src.indexOf('async function appliquerEtiquetteConcierge(sql, client, st) {');
let i = src.indexOf('{', debut), prof = 0, fin = i;
for (; fin < src.length; fin++) { if (src[fin] === '{') prof++; else if (src[fin] === '}' && --prof === 0) break; }
const corps = src.slice(debut, fin + 1);
const c = new pg.Client(); await c.connect();
let ok = 0, ko = 0; const eq = (n, a, b) => { if (JSON.stringify(a) === JSON.stringify(b)) ok++; else { ko++; console.log('ECHEC', n, JSON.stringify(a), '!=', JSON.stringify(b)); } };
try {
await c.query('BEGIN');
await c.query('ALTER TABLE etiquette_branchement ADD COLUMN IF NOT EXISTS applique_depuis timestamptz');
const journal = [];
const deps = {
txt: (x) => (x ?? '').toString().trim(), LABELS: new Set(['VW', 'JEEP', 'MEGANE', 'INVITE', 'ZERO']),
HOUSEHOLD: new Set(['VW', 'JEEP']), CANAUX_HUMAINS: new Set(['whatsapp', 'proprietaire']), DRY: false,
journaliser: async (sql, g, r, d) => { journal.push(r); await sql(`INSERT INTO evenement (genre, source, resume, detail) VALUES ($1,'test',$2,$3)`, [g, r, JSON.stringify(d || {})]); },
piloterSelecteurVehicule: async () => 0,
};
const fn = new Function(...Object.keys(deps), 'let dernierBlancVu = null; return (' + corps.replace('async function appliquerEtiquetteConcierge', 'async function') + ');')(...Object.values(deps));
const sql = (q, p) => c.query(q, p);
const st = (label, conf) => new Map([
['input_text.airtria_vehicle_label', { state: JSON.stringify({ branchement: '2026-10-04 16:55:45.120519+02', label, confirmed_at: conf, source: 'whatsapp' }) }],
['input_boolean.airtria_concierge_enabled', { state: 'on' }]]);
// Une session terminee AVANT la correction, pour verifier qu'elle garde JEEP.
await c.query(`INSERT INTO session_charge (debut, fin, terminee, vehicule, vehicule_sur, energie_kwh, energie_station_kwh)
VALUES ('2026-10-04T14:56:00Z','2026-10-04T14:56:30Z',true,'JEEP',true,0.05,0.1)`);
await c.query(`INSERT INTO evenement (genre, source, resume, detail) VALUES ('vehicule','test','avant',$1)`,
[JSON.stringify({ origine: 'airtria', label: 'JEEP', sessions: ['2026-10-04T14:56:00.000Z', '2026-10-04T14:56:55.447Z'] })]);
await fn(sql, c, st('ZERO', '2026-10-04T15:16:50.000Z'));
const s = (await c.query(`SELECT debut, vehicule, vehicule_sur FROM session_charge WHERE debut BETWEEN '2026-10-04T14:50Z' AND '2026-10-04T16:00Z' ORDER BY debut`)).rows;
eq('session terminee avant la correction garde JEEP', s[0].vehicule, 'JEEP');
eq('session en cours a 17:16 passe ZERO, confirmee', [s[1].vehicule, s[1].vehicule_sur], ['ZERO', true]);
const e = (await c.query(`SELECT label, applique_depuis FROM etiquette_branchement WHERE branchement = '2026-10-04T14:55:45.120Z'`)).rows[0];
eq('etiquette du branchement = ZERO depuis 17:16:50', [e.label, e.applique_depuis?.toISOString()], ['ZERO', '2026-10-04T15:16:50.000Z']);
eq('journal de correction', journal.some(r => r.startsWith('Etiquette corrigee par le proprietaire : JEEP -> ZERO')), true);
eq('pas de refus', journal.some(r => r.includes('REFUSEE')), false);
// Une contradiction NON humaine reste refusee.
journal.length = 0;
const st2 = new Map([['input_text.airtria_vehicle_label', { state: JSON.stringify({ branchement: '2026-10-04 16:55:45.120519+02', label: 'MEGANE', confirmed_at: '2026-10-04T15:30:00.000Z', source: 'regle-puissance' }) }],
['input_boolean.airtria_concierge_enabled', { state: 'on' }]]);
await fn(sql, c, st2);
eq('contradiction par la regle de puissance : refusee', journal.some(r => r.includes('REFUSEE')), true);
} finally { await c.query('ROLLBACK'); await c.end(); }
console.log(`${ok}/${ok + ko}`); process.exit(ko ? 1 : 0);