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:
@@ -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({
|
||||
|
||||
8
todo.md
8
todo.md
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user