/** * Seed des bases de répartition OPEX (charges classe 6) pour 2025 et 2026 * depuis les fichiers JSON sources. * * Inclut désormais la colonne baseRepartitionHep (pôle HEP uniquement). * Données 2026 extraites du fichier Excel source via extract_bases_repartition.py. * * Usage: node scripts/seed-opex-bases.mjs */ import mysql from 'mysql2/promise'; import { readFileSync } from 'fs'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; import dotenv from 'dotenv'; const __dirname = dirname(fileURLToPath(import.meta.url)); dotenv.config({ path: join(__dirname, '..', '.env') }); const conn = await mysql.createConnection(process.env.DATABASE_URL); // ── Année 2025 — depuis le JSON source (pas de colonne HEP disponible) ──────── { const annee = 2025; const filePath = join(__dirname, '../client/src/data_opex_2025.json'); const data = JSON.parse(readFileSync(filePath, 'utf8')); const etabs = data.etablissements || []; if (etabs.length === 0) { console.log(`Année ${annee}: aucun établissement trouvé dans le JSON`); } else { await conn.execute('DELETE FROM opex_bases_repartition WHERE annee = ?', [annee]); const values = etabs.map(e => [ annee, e.code, e.nom || null, e.base_repartition || 0, 0, // baseRepartitionHep non disponible pour 2025 ]); await conn.query( 'INSERT INTO opex_bases_repartition (annee, etablissementCode, etablissementNom, baseRepartition, baseRepartitionHep) VALUES ?', [values] ); console.log(`Année ${annee}: ${values.length} bases de répartition insérées (HEP: non disponible → 0)`); console.log(` Total base: ${etabs.reduce((s, e) => s + (e.base_repartition || 0), 0).toLocaleString('fr-FR', { maximumFractionDigits: 0 })} €`); } } // ── Année 2026 — depuis le JSON extrait du fichier Excel source ─────────────── // Données extraites par /home/ubuntu/extract_bases_repartition.py // Fichier: /home/ubuntu/bases_repartition_2026.json { const annee = 2026; let bases2026; try { bases2026 = JSON.parse(readFileSync('/home/ubuntu/bases_repartition_2026.json', 'utf8')); } catch (e) { console.error('Fichier bases_repartition_2026.json non trouvé. Fallback sur le JSON source.'); const filePath = join(__dirname, '../client/src/data_opex.json'); const data = JSON.parse(readFileSync(filePath, 'utf8')); bases2026 = (data.etablissements || []).map(e => ({ code: e.code, nom: e.nom, base_repartition: e.base_repartition || 0, base_repartition_hep: 0, })); } // Filtrer les lignes parasites (totaux, applicatifs, etc.) const etablissements = bases2026.filter(e => { const code = String(e.code).trim(); const nom = String(e.nom || '').trim().toLowerCase(); if (code.length < 4) return false; if (nom.includes('total') || nom.includes('applicatif') || nom.includes('téléphonie')) return false; // Exclure les lignes dont le code ressemble à un montant (ex: "504980") if (/^\d{5,}$/.test(code)) return false; return true; }); await conn.execute('DELETE FROM opex_bases_repartition WHERE annee = ?', [annee]); const values = etablissements.map(e => [ annee, String(e.code).trim(), String(e.nom || '').trim() || null, e.base_repartition || 0, e.base_repartition_hep || 0, ]); if (values.length > 0) { await conn.query( 'INSERT INTO opex_bases_repartition (annee, etablissementCode, etablissementNom, baseRepartition, baseRepartitionHep) VALUES ?', [values] ); } const totalBase = etablissements.reduce((s, e) => s + (e.base_repartition || 0), 0); const totalHep = etablissements.reduce((s, e) => s + (e.base_repartition_hep || 0), 0); const nbHep = etablissements.filter(e => (e.base_repartition_hep || 0) > 0).length; console.log(`Année ${annee}: ${values.length} bases de répartition insérées`); console.log(` Total base standard: ${totalBase.toLocaleString('fr-FR', { maximumFractionDigits: 0 })} €`); console.log(` Total base HEP: ${totalHep.toLocaleString('fr-FR', { maximumFractionDigits: 0 })} € (${nbHep} établissements HEP)`); } await conn.end(); console.log('\n✅ Seed bases de répartition terminé.');