Checkpoint: Modification du stockage des signatures d'émargement pour utiliser le système de fichiers local au lieu de S3 :

- Remplacement de storagePut par fs.writeFileSync dans routers.ts
- Structure de dossiers : uploads/signatures/[formation-id]-[sequence-id]/
- Noms de fichiers uniques avec crypto.randomBytes
- URLs publiques relatives : /uploads/signatures/[formation-id]-[sequence-id]/[fichier].png
- Correction de l'erreur "fetch failed" causée par l'inaccessibilité de forge.manus.im sur le VPS
This commit is contained in:
Manus
2026-01-27 07:28:09 -05:00
parent 1e915acd5b
commit 5356819ceb
2 changed files with 40 additions and 7 deletions

View File

@@ -2503,18 +2503,43 @@ export const appRouter = router({
}
}
// Uploader la signature en S3 si fournie
// Stocker la signature localement si fournie
let signatureUrl: string | undefined;
let signatureS3Key: string | undefined;
if (input.signatureDataUrl) {
const { storagePut } = await import("./storage");
const fs = await import("fs");
const path = await import("path");
const crypto = await import("crypto");
// Récupérer l'inscription pour obtenir la séquence
const inscriptionData = await db.select().from(inscriptions).where(eq(inscriptions.id, input.inscriptionId)).limit(1);
if (inscriptionData.length === 0) throw new Error("Inscription introuvable");
const sequenceData = await db.select().from(sequences).where(eq(sequences.id, inscriptionData[0].sequenceId)).limit(1);
if (sequenceData.length === 0) throw new Error("Séquence introuvable");
const formationId = sequenceData[0].formationId;
const sequenceId = sequenceData[0].id;
// Créer la structure de dossiers
const uploadsDir = path.resolve(process.cwd(), "uploads", "signatures", `${formationId}-${sequenceId}`);
if (!fs.existsSync(uploadsDir)) {
fs.mkdirSync(uploadsDir, { recursive: true });
}
// Générer un nom de fichier unique
const randomSuffix = crypto.randomBytes(8).toString("hex");
const fileName = `signature-${input.inscriptionId}-${input.dateFormationId}-${randomSuffix}.png`;
const filePath = path.join(uploadsDir, fileName);
// Convertir le data URL en buffer et sauvegarder
const base64Data = input.signatureDataUrl.split(",")[1];
const buffer = Buffer.from(base64Data, "base64");
const randomSuffix = Math.random().toString(36).substring(7);
const s3Key = `signatures/presence-${input.inscriptionId}-${input.dateFormationId}-${randomSuffix}.png`;
const { url } = await storagePut(s3Key, buffer, "image/png");
signatureUrl = url;
signatureS3Key = s3Key;
fs.writeFileSync(filePath, buffer);
// Générer l'URL publique
signatureUrl = `/uploads/signatures/${formationId}-${sequenceId}/${fileName}`;
signatureS3Key = `signatures/${formationId}-${sequenceId}/${fileName}`;
}
const result = await validerPresence({

View File

@@ -1303,3 +1303,11 @@
- [ ] Intégrer les signatures dans la feuille de présence PDF (optionnel)
- [ ] Tester le flux complet sur smartphone
- [ ] Déployer sur le VPS
## Stockage local des signatures d'émargement
- [ ] Modifier routers.ts pour stocker les signatures localement au lieu de S3
- [ ] Créer la structure de dossiers uploads/signatures/[formation-id]-[sequence-id]/
- [ ] Générer des noms de fichiers uniques pour chaque signature
- [ ] Configurer Nginx pour servir les fichiers de signatures
- [ ] Tester le flux complet sur le VPS