espace-paie-odentas/app/api/odentas-sign/requests/[id]/route.ts
odentas b790faf12c feat: Implémentation complète du système Odentas Sign
- Remplacement de DocuSeal par solution souveraine Odentas Sign
- Système d'authentification OTP pour signataires (bcryptjs + JWT)
- 8 routes API: send-otp, verify-otp, sign, pdf-url, positions, status, webhook, signers
- Interface moderne avec canvas de signature et animations (framer-motion, confetti)
- Système de templates pour auto-détection des positions de signature (CDDU, RG, avenants)
- PDF viewer avec @react-pdf-viewer (compatible Next.js)
- Stockage S3: source/, signatures/, evidence/, signed/, certs/
- Tables Supabase: sign_requests, signers, sign_positions, sign_events, sign_assets
- Evidence bundle automatique (JSON metadata + timestamps)
- Templates emails: OTP et completion
- Scripts Lambda prêts: pades-sign (KMS seal) et tsaStamp (RFC3161)
- Mode test détecté automatiquement (emails whitelist)
- Tests complets avec PDF CDDU réel (2 signataires)
2025-10-27 19:03:07 +01:00

71 lines
2 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import { supabaseAdmin } from '@/lib/odentas-sign/supabase';
/**
* GET /api/odentas-sign/requests/[id]
*
* Récupère les détails d'une demande de signature
*/
export async function GET(
request: NextRequest,
{ params }: { params: { id: string } }
) {
try {
const requestId = params.id;
// Récupérer la demande avec tous ses signataires et positions
const { data: signRequest, error: requestError } = await supabaseAdmin
.from('sign_requests')
.select(`
*,
signers(*),
sign_positions(*)
`)
.eq('id', requestId)
.single();
if (requestError || !signRequest) {
return NextResponse.json(
{ error: 'Demande de signature introuvable' },
{ status: 404 }
);
}
// Calculer le statut de progression
const totalSigners = signRequest.signers?.length || 0;
const signedCount = signRequest.signers?.filter((s: any) => s.signed_at !== null).length || 0;
return NextResponse.json({
success: true,
request: {
id: signRequest.id,
ref: signRequest.ref,
title: signRequest.title,
source_s3_key: signRequest.source_s3_key,
status: signRequest.status,
created_at: signRequest.created_at,
progress: {
total: totalSigners,
signed: signedCount,
percentage: totalSigners > 0 ? Math.round((signedCount / totalSigners) * 100) : 0,
},
},
signers: signRequest.signers?.map((s: any) => ({
id: s.id,
role: s.role,
name: s.name,
email: s.email,
signed_at: s.signed_at,
signature_image_s3: s.signature_image_s3,
})) || [],
positions: signRequest.sign_positions || [],
});
} catch (error) {
console.error('[GET REQUEST] Erreur:', error);
return NextResponse.json(
{ error: 'Erreur serveur', details: error instanceof Error ? error.message : String(error) },
{ status: 500 }
);
}
}