fix: gridAllowedBySoc + nightTakeoverLatched - autorise HC nuit et libère takeover après charge

This commit is contained in:
Tallagrand Thierry
2026-08-04 19:41:31 +02:00
parent 3ae047231b
commit 3beefff8de
2 changed files with 223 additions and 2 deletions

View File

@@ -0,0 +1,161 @@
#!/usr/bin/env node
const N8N_URL = process.env.N8N_URL || 'https://n8n.airtria.pro';
const N8N_API_KEY = process.env.N8N_API_KEY;
const WORKFLOW_ID = process.env.WORKFLOW_ID || 'ATswvGfG4KJUls0K';
if (!N8N_API_KEY) {
console.error('❌ Erreur: N8N_API_KEY non défini');
console.error(' Exportez la variable: export N8N_API_KEY="votre_token"');
process.exit(1);
}
const headers = {
'X-N8N-API-KEY': N8N_API_KEY,
'Content-Type': 'application/json'
};
async function main() {
console.log('=== Test PUT workflow n8n ===\n');
console.log(`URL: ${N8N_URL}/api/v1/workflows/${WORKFLOW_ID}`);
console.log(`Workflow ID: ${WORKFLOW_ID}\n`);
// 1. Lire le workflow
console.log('1️⃣ Lecture du workflow via GET...');
let getResponse;
try {
getResponse = await fetch(`${N8N_URL}/api/v1/workflows/${WORKFLOW_ID}`, {
method: 'GET',
headers
});
} catch (err) {
console.error('❌ Erreur réseau GET:', err.message);
process.exit(1);
}
if (!getResponse.ok) {
console.error(`❌ GET échoué: ${getResponse.status} ${getResponse.statusText}`);
const text = await getResponse.text();
console.error('Réponse:', text);
process.exit(1);
}
const workflow = await getResponse.json();
console.log(`✅ Workflow lu: "${workflow.name}" (${workflow.nodes?.length || 0} nodes)`);
// 2. Sauvegarde locale
const backupPath = `./backup-workflow-${WORKFLOW_ID}-${Date.now()}.json`;
console.log(`\n2️⃣ Sauvegarde locale: ${backupPath}`);
const fs = await import('fs');
fs.writeFileSync(backupPath, JSON.stringify(workflow, null, 2));
console.log('✅ Backup créé');
// 3. Reconstruire body propre (settings minimal)
const body = {
name: workflow.name,
nodes: workflow.nodes,
connections: workflow.connections,
settings: {
executionOrder: workflow.settings?.executionOrder || 'v1',
callerPolicy: workflow.settings?.callerPolicy || 'workflowsFromSameOwner'
},
staticData: workflow.staticData
};
console.log('\n3️⃣ Body reconstruit (champs inclus):');
console.log(' - name:', body.name);
console.log(' - nodes:', body.nodes?.length || 0);
console.log(' - connections:', body.connections ? 'présent' : 'absent');
console.log(' - settings:', JSON.stringify(body.settings));
console.log(' - staticData:', body.staticData ? 'présent' : 'absent');
// 4. Appliquer les corrections
console.log('\n4️⃣ Application des corrections...');
// Trouver le node BATTERY_CLOUD_LOCKS
const batteryCloudLocksNode = body.nodes.find(n => n.name === 'BATTERY_CLOUD_LOCKS');
if (!batteryCloudLocksNode) {
console.error('❌ Node BATTERY_CLOUD_LOCKS non trouvé');
process.exit(1);
}
let jsCode = batteryCloudLocksNode.parameters.jsCode;
// Fix 1: gridAllowedBySoc - ajouter context.profile === 'night_hc'
const fix1Old = 'const gridAllowedBySoc = parsed.soc <= 35 || strategy.forceGridRequested;';
const fix1New = `const gridAllowedBySoc =
strategy.forceGridRequested ||
context.profile === 'night_hc' ||
parsed.soc <= 35;`;
if (jsCode.includes(fix1Old)) {
jsCode = jsCode.replace(fix1Old, fix1New);
console.log(' ✅ Fix 1 appliqué: gridAllowedBySoc');
} else {
console.log(' ⚠️ Fix 1: pattern non trouvé (déjà appliqué?)');
}
// Fix 2: nightTakeoverLatched - libérer quand charge terminée (soc >= 50)
const fix2Old = `const nightTakeoverLatched =
nightSessionActive &&
nightTakeoverPrev &&
parsed.soc < NIGHT_TAKEOVER_RELEASE_SOC_PCT;`;
const fix2New = `const vehicleChargeCompleted =
!parsed.evcsChargingSwitchOn &&
parsed.soc >= 50;
const nightTakeoverLatched =
nightSessionActive &&
nightTakeoverPrev &&
(
parsed.soc < NIGHT_TAKEOVER_RELEASE_SOC_PCT ||
vehicleChargeCompleted
);`;
if (jsCode.includes(fix2Old)) {
jsCode = jsCode.replace(fix2Old, fix2New);
console.log(' ✅ Fix 2 appliqué: nightTakeoverLatched');
} else {
console.log(' ⚠️ Fix 2: pattern non trouvé (déjà appliqué?)');
}
batteryCloudLocksNode.parameters.jsCode = jsCode;
// 5. Tenter PUT
console.log('\n5️⃣ Tentative PUT...');
let putResponse;
try {
putResponse = await fetch(`${N8N_URL}/api/v1/workflows/${WORKFLOW_ID}`, {
method: 'PUT',
headers,
body: JSON.stringify(body)
});
} catch (err) {
console.error('❌ Erreur réseau PUT:', err.message);
process.exit(1);
}
const putStatus = putResponse.status;
const putStatusText = putResponse.statusText;
const putResponseText = await putResponse.text();
console.log(`\n📊 Résultat PUT:`);
console.log(` Status: ${putStatus} ${putStatusText}`);
if (putResponse.ok) {
console.log('✅ PUT réussi!');
const putJson = JSON.parse(putResponseText);
console.log(` Workflow mis à jour: "${putJson.name}"`);
} else {
console.log('❌ PUT REFUSÉ par n8n');
console.log('\n📄 Erreur exacte:');
try {
const errorJson = JSON.parse(putResponseText);
console.log(JSON.stringify(errorJson, null, 2));
} catch {
console.log(putResponseText);
}
}
}
main();