espace-paie-odentas/scripts/verify-pdfmonkey-data.js

543 lines
No EOL
16 KiB
JavaScript

#!/usr/bin/env node
/**
* Script de vérification des données Supabase pour PDFMonkey
*
* Ce script vérifie si toutes les données nécessaires pour générer
* un contrat avec PDFMonkey sont disponibles dans les tables Supabase.
*/
import { createClient } from '@supabase/supabase-js';
import { config } from 'dotenv';
// Charger les variables d'environnement
config({ path: '.env.local' });
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
const supabaseServiceKey = process.env.SUPABASE_SERVICE_ROLE_KEY;
if (!supabaseUrl || !supabaseServiceKey) {
console.error('❌ Variables d\'environnement manquantes:');
console.error(' NEXT_PUBLIC_SUPABASE_URL:', !!supabaseUrl ? '✅' : '❌');
console.error(' SUPABASE_SERVICE_ROLE_KEY:', !!supabaseServiceKey ? '✅' : '❌');
process.exit(1);
}
const supabase = createClient(supabaseUrl, supabaseServiceKey);
// Mapping des champs PDFMonkey vers les tables Supabase
const PDFMONKEY_MAPPING = {
// === STRUCTURE/CLIENT DATA ===
structure_name: {
table: 'organizations',
column: 'structure_api', // ou 'name'
description: 'Nom de la structure'
},
structure_adresse: {
table: 'organizations',
column: 'address', // À vérifier
description: 'Adresse de la structure'
},
structure_cpville: {
table: 'organizations',
column: 'postal_code', // À vérifier
description: 'Code postal de la structure'
},
structure_ville: {
table: 'organizations',
column: 'city', // À vérifier
description: 'Ville de la structure'
},
structure_siret: {
table: 'organizations',
column: 'siret', // À vérifier
description: 'SIRET de la structure'
},
structure_licence: {
table: 'organizations',
column: 'licence_spectacles', // À vérifier
description: 'Licence spectacles'
},
structure_spectacle: {
table: 'productions',
column: 'name',
description: 'Nom du spectacle/production'
},
forme_juridique: {
table: 'organizations',
column: 'legal_form', // À vérifier
description: 'Forme juridique'
},
structure_signataire: {
table: 'organizations',
column: 'signatory_name', // À vérifier (concat prénom + nom)
description: 'Nom complet du signataire'
},
structure_signatairequalite: {
table: 'organizations',
column: 'signatory_title', // À vérifier
description: 'Qualité du signataire'
},
delegation: {
table: 'organizations',
column: 'delegation_authority', // À vérifier
description: 'Signataire agissant par délégation'
},
// === EMPLOYEE DATA ===
employee_civ: {
table: 'salaries',
column: 'civilite',
description: 'Civilité du salarié'
},
employee_firstname: {
table: 'salaries',
column: 'prenom',
description: 'Prénom du salarié'
},
employee_lastname: {
table: 'salaries',
column: 'nom',
description: 'Nom du salarié'
},
employee_birthname: {
table: 'salaries',
column: 'nom_naissance', // À vérifier
description: 'Nom de naissance'
},
employee_pseudo: {
table: 'salaries',
column: 'pseudonyme', // À vérifier
description: 'Pseudonyme'
},
employee_dob: {
table: 'salaries',
column: 'date_naissance', // À vérifier
description: 'Date de naissance'
},
employee_cob: {
table: 'salaries',
column: 'lieu_naissance', // À vérifier
description: 'Lieu de naissance'
},
employee_address: {
table: 'salaries',
column: 'adresse', // À vérifier
description: 'Adresse du salarié'
},
employee_ss: {
table: 'salaries',
column: 'nir', // À vérifier
description: 'Numéro de sécurité sociale'
},
employee_cs: {
table: 'salaries',
column: 'conges_spectacles', // À vérifier
description: 'Congés Spectacles'
},
employee_profession: {
table: 'cddu_contracts', // ou salaries
column: 'profession',
description: 'Profession'
},
employee_codeprofession: {
table: 'cddu_contracts',
column: 'code_profession', // À vérifier
description: 'Code profession'
},
employee_catpro: {
table: 'cddu_contracts',
column: 'categorie_pro',
description: 'Catégorie professionnelle'
},
// === CONTRACT DATA ===
mineur1618: {
table: 'cddu_contracts',
column: 'mineur_entre_16_et_18',
description: 'Mineur entre 16 et 18 ans'
},
representant_civ: {
table: 'cddu_contracts',
column: 'civilite_representant_legal',
description: 'Civilité représentant légal'
},
representant_nom: {
table: 'cddu_contracts',
column: 'nom_representant_legal',
description: 'Nom représentant légal'
},
representant_dob: {
table: 'cddu_contracts',
column: 'dob_representant_legal',
description: 'Date naissance représentant légal'
},
representant_cob: {
table: 'cddu_contracts',
column: 'cob_representant_legal', // À vérifier
description: 'Lieu naissance représentant légal'
},
representant_adresse: {
table: 'cddu_contracts',
column: 'adresse_representant_legal',
description: 'Adresse représentant légal'
},
spectacle: {
table: 'cddu_contracts',
column: 'production_name',
description: 'Nom du spectacle'
},
numobjet: {
table: 'cddu_contracts',
column: 'objet_spectacle', // ou numero_objet
description: 'Numéro/objet spectacle'
},
type_numobjet: {
table: 'cddu_contracts',
column: 'type_numero_objet', // À vérifier
description: 'Type numéro objet'
},
date_debut: {
table: 'cddu_contracts',
column: 'start_date',
description: 'Date de début'
},
date_fin: {
table: 'cddu_contracts',
column: 'end_date',
description: 'Date de fin'
},
dates_travaillees: {
table: 'cddu_contracts',
column: 'jours_travail', // À vérifier
description: 'Jours travaillés'
},
autreprecision: {
table: 'cddu_contracts',
column: 'autre_precision_salaire', // À vérifier
description: 'Autre précision salaire'
},
salaire_brut: {
table: 'cddu_contracts',
column: 'brut',
description: 'Salaire brut'
},
date_signature: {
table: 'cddu_contracts',
column: 'date_signature_contrat', // À vérifier
description: 'Date de signature'
},
CCN: {
table: 'cddu_contracts',
column: 'ccn', // À vérifier
description: 'Convention collective'
},
precisions_salaire: {
table: 'cddu_contracts',
column: 'precisions_salaire',
description: 'Précisions salaire'
},
panierrepas: {
table: 'cddu_contracts',
column: 'panier_repas',
description: 'Panier repas'
},
panierrepasccn: {
table: 'cddu_contracts',
column: 'panier_repas_ccn',
description: 'Panier repas CCN'
},
montantpanierrepas: {
table: 'cddu_contracts',
column: 'si_non_montant_par_panier',
description: 'Montant panier repas'
},
// === CACHETS DATA ===
'cachets.representations': {
table: 'cddu_contracts',
column: 'cachets_representations',
description: 'Cachets représentations'
},
'cachets.repetitions': {
table: 'cddu_contracts',
column: 'services_repetitions',
description: 'Services répétitions'
},
'cachets.heures': {
table: 'cddu_contracts',
column: 'nombre_d_heures',
description: 'Nombre d\'heures'
},
'cachets.heuresparjour': {
table: 'cddu_contracts',
column: 'nombre_d_heures_par_jour',
description: 'Heures par jour'
},
// === RESPONSABLE TRAITEMENT DATA ===
nom_responsable_traitement: {
table: 'organizations',
column: 'data_controller_name', // À vérifier
description: 'Nom responsable traitement'
},
qualite_responsable_traitement: {
table: 'organizations',
column: 'data_controller_title', // À vérifier
description: 'Qualité responsable traitement'
},
email_responsable_traitement: {
table: 'organizations',
column: 'data_controller_email', // À vérifier
description: 'Email responsable traitement'
},
imageUrl: {
table: 'organizations',
column: 'logo_base64', // À vérifier
description: 'Logo en base64'
}
};
/**
* Vérification de l'existence des colonnes dans les tables
*/
async function checkTableColumns() {
console.log('📊 Vérification des colonnes existantes dans Supabase...\n');
const tables = ['organizations', 'salaries', 'cddu_contracts', 'productions'];
const tableColumns = {};
for (const table of tables) {
try {
console.log(`🔍 Table: ${table}`);
// Récupérer un échantillon pour voir les colonnes disponibles
const { data, error } = await supabase
.from(table)
.select('*')
.limit(1);
if (error) {
console.log(` ❌ Erreur: ${error.message}`);
tableColumns[table] = [];
} else if (data && data.length > 0) {
const columns = Object.keys(data[0]);
tableColumns[table] = columns;
console.log(`${columns.length} colonnes trouvées`);
console.log(` 📋 Colonnes: ${columns.join(', ')}`);
} else {
console.log(` ⚠️ Table vide, récupération du schéma...`);
// Essayer une requête pour voir les colonnes même si vide
const { error: schemaError } = await supabase
.from(table)
.select('*')
.limit(0);
if (!schemaError) {
tableColumns[table] = [];
console.log(` 📋 Table existe mais est vide`);
}
}
console.log('');
} catch (err) {
console.log(` ❌ Erreur inattendue: ${err.message}\n`);
tableColumns[table] = [];
}
}
return tableColumns;
}
/**
* Analyse des champs requis vs disponibles
*/
async function analyzePDFMonkeyMapping(tableColumns) {
console.log('🎯 Analyse des champs requis pour PDFMonkey...\n');
const results = {
available: [],
missing: [],
uncertain: []
};
for (const [pdfField, mapping] of Object.entries(PDFMONKEY_MAPPING)) {
const { table, column, description } = mapping;
const availableColumns = tableColumns[table] || [];
if (availableColumns.includes(column)) {
results.available.push({ pdfField, table, column, description, status: '✅ Disponible' });
} else if (availableColumns.length === 0) {
results.uncertain.push({ pdfField, table, column, description, status: '❓ Table non accessible' });
} else {
results.missing.push({ pdfField, table, column, description, status: '❌ Manquant' });
}
}
return results;
}
/**
* Suggestions de colonnes similaires
*/
function findSimilarColumns(targetColumn, availableColumns) {
const similar = availableColumns.filter(col =>
col.toLowerCase().includes(targetColumn.toLowerCase()) ||
targetColumn.toLowerCase().includes(col.toLowerCase())
);
return similar;
}
/**
* Rapport détaillé
*/
function printDetailedReport(results, tableColumns) {
console.log('📈 RAPPORT DÉTAILLÉ\n');
console.log('='.repeat(80));
// Statistiques
const total = results.available.length + results.missing.length + results.uncertain.length;
console.log(`📊 STATISTIQUES:`);
console.log(` Total des champs requis: ${total}`);
console.log(` ✅ Disponibles: ${results.available.length} (${Math.round(results.available.length/total*100)}%)`);
console.log(` ❌ Manquants: ${results.missing.length} (${Math.round(results.missing.length/total*100)}%)`);
console.log(` ❓ Incertains: ${results.uncertain.length} (${Math.round(results.uncertain.length/total*100)}%)`);
console.log('');
// Champs disponibles
if (results.available.length > 0) {
console.log('✅ CHAMPS DISPONIBLES:');
console.log('-'.repeat(50));
results.available.forEach(item => {
console.log(` ${item.pdfField}: ${item.table}.${item.column}`);
console.log(`${item.description}`);
});
console.log('');
}
// Champs manquants avec suggestions
if (results.missing.length > 0) {
console.log('❌ CHAMPS MANQUANTS:');
console.log('-'.repeat(50));
results.missing.forEach(item => {
console.log(` ${item.pdfField}: ${item.table}.${item.column} (MANQUANT)`);
console.log(`${item.description}`);
// Chercher des colonnes similaires
const availableColumns = tableColumns[item.table] || [];
const similar = findSimilarColumns(item.column, availableColumns);
if (similar.length > 0) {
console.log(` 💡 Suggestions: ${similar.join(', ')}`);
}
console.log('');
});
}
// Champs incertains
if (results.uncertain.length > 0) {
console.log('❓ CHAMPS INCERTAINS (table inaccessible):');
console.log('-'.repeat(50));
results.uncertain.forEach(item => {
console.log(` ${item.pdfField}: ${item.table}.${item.column}`);
console.log(`${item.description}`);
});
console.log('');
}
}
/**
* Générer un exemple de requête
*/
function generateExampleQuery(results) {
console.log('💡 EXEMPLE DE REQUÊTE POUR RÉCUPÉRER LES DONNÉES:');
console.log('-'.repeat(60));
const availableByTable = {};
results.available.forEach(item => {
if (!availableByTable[item.table]) {
availableByTable[item.table] = [];
}
availableByTable[item.table].push(item.column);
});
console.log('```javascript');
console.log('async function getPDFMonkeyData(contractId) {');
console.log(' const supabase = createClient(...);');
console.log(' ');
Object.entries(availableByTable).forEach(([table, columns]) => {
const uniqueColumns = [...new Set(columns)];
console.log(` // Données de la table ${table}`);
console.log(` const { data: ${table}Data } = await supabase`);
console.log(` .from('${table}')`);
console.log(` .select('${uniqueColumns.join(', ')}')`);
if (table === 'cddu_contracts') {
console.log(` .eq('id', contractId)`);
}
console.log(` .single();`);
console.log(' ');
});
console.log(' const dataPayload = {');
results.available.forEach(item => {
const varName = item.table === 'cddu_contracts' ? 'cddu_contractsData' : `${item.table}Data`;
console.log(` ${item.pdfField}: ${varName}?.${item.column} || "",`);
});
console.log(' // TODO: Ajouter les champs manquants');
console.log(' };');
console.log(' ');
console.log(' return dataPayload;');
console.log('}');
console.log('```');
}
/**
* Fonction principale
*/
async function main() {
console.log('🚀 Vérification des données Supabase pour PDFMonkey');
console.log('='.repeat(80));
console.log('');
try {
// 1. Vérifier les colonnes des tables
const tableColumns = await checkTableColumns();
// 2. Analyser le mapping PDFMonkey
const results = await analyzePDFMonkeyMapping(tableColumns);
// 3. Afficher le rapport détaillé
printDetailedReport(results, tableColumns);
// 4. Générer un exemple de requête
generateExampleQuery(results);
// 5. Résumé final
console.log('\n📋 ACTIONS RECOMMANDÉES:');
console.log('-'.repeat(30));
if (results.missing.length > 0) {
console.log('1. 🔧 Ajouter les colonnes manquantes dans les tables Supabase');
console.log('2. 📝 Créer des migrations pour ajouter ces colonnes');
console.log('3. 🔄 Migrer les données existantes d\'Airtable vers Supabase');
}
if (results.available.length > 30) {
console.log('4. ✅ Créer une API endpoint pour récupérer toutes les données');
console.log('5. 🧪 Tester la génération PDFMonkey avec les données Supabase');
}
console.log('\n🎯 Prêt à remplacer Airtable:', results.available.length >= 40 ? '✅ OUI' : '❌ NON');
} catch (error) {
console.error('❌ Erreur lors de l\'analyse:', error.message);
process.exit(1);
}
}
// Exécuter le script
if (import.meta.url === `file://${process.argv[1]}`) {
main();
}
export { PDFMONKEY_MAPPING, checkTableColumns, analyzePDFMonkeyMapping };