- Ajout colonne employee_docuseal_slug dans cddu_contracts - Stockage automatique du slug lors de création signature DocuSeal - Recherche directe par slug (+ rapide et fiable) - Bypass mode maintenance en localhost - Scripts de migration pour contrats existants (92 contrats migrés) - Logs détaillés dans verify-birthdate et check-status Fixes: Erreur 'Document introuvable' pour contrats anciens Performance: O(n) -> O(1) avec index sur employee_docuseal_slug
146 lines
4.8 KiB
TypeScript
146 lines
4.8 KiB
TypeScript
/**
|
||
* Script de migration pour récupérer les slugs DocuSeal des salariés
|
||
* et les stocker dans cddu_contracts.employee_docuseal_slug
|
||
*
|
||
* Usage: npx tsx scripts/migrate-employee-docuseal-slugs.ts
|
||
*/
|
||
|
||
import { createClient } from '@supabase/supabase-js';
|
||
import { config } from 'dotenv';
|
||
import { resolve } from 'path';
|
||
|
||
// Charger les variables d'environnement depuis .env.local
|
||
config({ path: resolve(process.cwd(), '.env.local') });
|
||
|
||
const SUPABASE_URL = process.env.NEXT_PUBLIC_SUPABASE_URL;
|
||
const SUPABASE_SERVICE_ROLE_KEY = process.env.SUPABASE_SERVICE_ROLE_KEY;
|
||
const DOCUSEAL_TOKEN = process.env.DOCUSEAL_TOKEN;
|
||
|
||
// Vérification des variables d'environnement
|
||
if (!SUPABASE_URL || !SUPABASE_SERVICE_ROLE_KEY || !DOCUSEAL_TOKEN) {
|
||
console.error('❌ Variables d\'environnement manquantes:');
|
||
if (!SUPABASE_URL) console.error(' - NEXT_PUBLIC_SUPABASE_URL');
|
||
if (!SUPABASE_SERVICE_ROLE_KEY) console.error(' - SUPABASE_SERVICE_ROLE_KEY');
|
||
if (!DOCUSEAL_TOKEN) console.error(' - DOCUSEAL_TOKEN');
|
||
process.exit(1);
|
||
}
|
||
|
||
const supabase = createClient(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY);
|
||
|
||
interface Contract {
|
||
id: number;
|
||
contract_number: string;
|
||
docuseal_submission_id: string;
|
||
employee_docuseal_slug: string | null;
|
||
}
|
||
|
||
async function getEmployeeSlugFromDocuSeal(submissionId: string): Promise<string | null> {
|
||
if (!DOCUSEAL_TOKEN) {
|
||
console.error('❌ DOCUSEAL_TOKEN non défini');
|
||
return null;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`https://api.docuseal.eu/submissions/${submissionId}`, {
|
||
method: 'GET',
|
||
headers: {
|
||
'X-Auth-Token': DOCUSEAL_TOKEN,
|
||
'Content-Type': 'application/json',
|
||
},
|
||
});
|
||
|
||
if (!response.ok) {
|
||
console.error(`❌ DocuSeal API error for submission ${submissionId}:`, response.status);
|
||
return null;
|
||
}
|
||
|
||
const data = await response.json();
|
||
const submitters = data.submitters || [];
|
||
const employeeSubmitter = submitters.find((s: any) => s.role === 'Salarié');
|
||
|
||
return employeeSubmitter?.slug || null;
|
||
} catch (error) {
|
||
console.error(`❌ Error fetching DocuSeal submission ${submissionId}:`, error);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
async function migrateEmployeeDocusealSlugs() {
|
||
console.log('🚀 Début de la migration des slugs DocuSeal des salariés...\n');
|
||
|
||
// 1. Récupérer tous les contrats qui ont un docuseal_submission_id mais pas de employee_docuseal_slug
|
||
const { data: contracts, error } = await supabase
|
||
.from('cddu_contracts')
|
||
.select('id, contract_number, docuseal_submission_id, employee_docuseal_slug')
|
||
.not('docuseal_submission_id', 'is', null)
|
||
.is('employee_docuseal_slug', null);
|
||
|
||
if (error) {
|
||
console.error('❌ Erreur lors de la récupération des contrats:', error);
|
||
return;
|
||
}
|
||
|
||
if (!contracts || contracts.length === 0) {
|
||
console.log('✅ Aucun contrat à migrer (tous les slugs sont déjà renseignés)');
|
||
return;
|
||
}
|
||
|
||
console.log(`📋 ${contracts.length} contrats à migrer\n`);
|
||
|
||
let successCount = 0;
|
||
let errorCount = 0;
|
||
let notFoundCount = 0;
|
||
|
||
// 2. Pour chaque contrat, récupérer le slug depuis DocuSeal
|
||
for (const contract of contracts as Contract[]) {
|
||
console.log(`🔄 Traitement du contrat ${contract.contract_number}...`);
|
||
|
||
const employeeSlug = await getEmployeeSlugFromDocuSeal(contract.docuseal_submission_id);
|
||
|
||
if (!employeeSlug) {
|
||
console.log(`⚠️ Slug non trouvé pour le contrat ${contract.contract_number}`);
|
||
notFoundCount++;
|
||
continue;
|
||
}
|
||
|
||
// 3. Mettre à jour le contrat avec le slug
|
||
const { error: updateError } = await supabase
|
||
.from('cddu_contracts')
|
||
.update({ employee_docuseal_slug: employeeSlug })
|
||
.eq('id', contract.id);
|
||
|
||
if (updateError) {
|
||
console.error(`❌ Erreur lors de la mise à jour du contrat ${contract.contract_number}:`, updateError);
|
||
errorCount++;
|
||
} else {
|
||
console.log(`✅ Contrat ${contract.contract_number} mis à jour avec le slug: ${employeeSlug}`);
|
||
successCount++;
|
||
}
|
||
|
||
// Pause pour éviter de surcharger l'API DocuSeal
|
||
await new Promise(resolve => setTimeout(resolve, 100));
|
||
}
|
||
|
||
// 4. Résumé
|
||
console.log('\n📊 Résumé de la migration:');
|
||
console.log(` ✅ Succès: ${successCount}`);
|
||
console.log(` ⚠️ Non trouvés: ${notFoundCount}`);
|
||
console.log(` ❌ Erreurs: ${errorCount}`);
|
||
console.log(` 📋 Total: ${contracts.length}`);
|
||
|
||
if (successCount === contracts.length) {
|
||
console.log('\n🎉 Migration terminée avec succès !');
|
||
} else if (successCount > 0) {
|
||
console.log('\n⚠️ Migration partiellement réussie');
|
||
} else {
|
||
console.log('\n❌ Migration échouée');
|
||
}
|
||
}
|
||
|
||
// Exécuter la migration
|
||
migrateEmployeeDocusealSlugs()
|
||
.then(() => process.exit(0))
|
||
.catch((error) => {
|
||
console.error('❌ Erreur fatale:', error);
|
||
process.exit(1);
|
||
});
|