Checkpoint: Système d'attestations de formation implémenté
✅ Infrastructure backend : - Tables attestations et configAttestation en base de données - Service de génération PDF avec PDFKit (attestationService.ts) - Génération automatique de PDF avec template personnalisable - Upload automatique vers S3 avec URLs publiques - Procédures tRPC pour générer, récupérer et configurer ✅ Interface utilisateur : - Page de configuration des attestations (/admin/attestations) - Personnalisation du texte avec variables dynamiques (nomComplet, nomFormation, dateDebut, dateFin) - Configuration du signataire (nom et fonction) - Bouton "Générer" dans la page de validation des présences formateur - Génération automatique avec ouverture du PDF dans un nouvel onglet ✅ Fonctionnalités : - Vérification des doublons (une seule attestation par apprenant/séquence) - Génération uniquement pour les apprenants marqués comme présents - PDF professionnel avec détails de la formation et dates - Stockage permanent sur S3 📋 Améliorations futures possibles : - Upload de logo et signature personnalisés - Envoi automatique par email aux apprenants - Espace apprenant pour télécharger les attestations
This commit is contained in:
2028
drizzle/meta/0024_snapshot.json
Normal file
2028
drizzle/meta/0024_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1848
drizzle/meta/0025_snapshot.json
Normal file
1848
drizzle/meta/0025_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
2028
drizzle/meta/0026_snapshot.json
Normal file
2028
drizzle/meta/0026_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -169,6 +169,27 @@
|
||||
"when": 1765830109012,
|
||||
"tag": "0023_jittery_gorgon",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 24,
|
||||
"version": "5",
|
||||
"when": 1767770858914,
|
||||
"tag": "0024_panoramic_goliath",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 25,
|
||||
"version": "5",
|
||||
"when": 1767795835957,
|
||||
"tag": "0025_curious_wrecker",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 26,
|
||||
"version": "5",
|
||||
"when": 1767798385842,
|
||||
"tag": "0026_panoramic_king_bedlam",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -520,3 +520,58 @@ export const logsNotifications = mysqlTable("logsNotifications", {
|
||||
|
||||
export type LogNotification = typeof logsNotifications.$inferSelect;
|
||||
export type InsertLogNotification = typeof logsNotifications.$inferInsert;
|
||||
|
||||
/**
|
||||
* Table des attestations de formation
|
||||
* Stocke les attestations générées pour chaque apprenant ayant terminé une formation
|
||||
*/
|
||||
export const attestations = mysqlTable("attestations", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
/** ID de l'inscription concernée */
|
||||
inscriptionId: int("inscriptionId").notNull(),
|
||||
/** ID de l'apprenant */
|
||||
apprenantId: int("apprenantId").notNull(),
|
||||
/** ID de la séquence */
|
||||
sequenceId: int("sequenceId").notNull(),
|
||||
/** Clé S3 du PDF généré */
|
||||
s3Key: varchar("s3Key", { length: 500 }).notNull(),
|
||||
/** URL publique du PDF */
|
||||
pdfUrl: varchar("pdfUrl", { length: 1000 }).notNull(),
|
||||
/** Date de génération de l'attestation */
|
||||
dateGeneration: timestamp("dateGeneration").defaultNow().notNull(),
|
||||
/** Statut de l'envoi par email */
|
||||
emailEnvoye: boolean("emailEnvoye").default(false).notNull(),
|
||||
/** Date d'envoi de l'email */
|
||||
dateEnvoiEmail: timestamp("dateEnvoiEmail"),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
});
|
||||
|
||||
export type Attestation = typeof attestations.$inferSelect;
|
||||
export type InsertAttestation = typeof attestations.$inferInsert;
|
||||
|
||||
/**
|
||||
* Table de configuration des attestations
|
||||
* Stocke le logo, la signature et le template personnalisable
|
||||
*/
|
||||
export const configAttestation = mysqlTable("configAttestation", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
/** Clé S3 du logo */
|
||||
logoS3Key: varchar("logoS3Key", { length: 500 }),
|
||||
/** URL du logo */
|
||||
logoUrl: varchar("logoUrl", { length: 1000 }),
|
||||
/** Clé S3 de la signature */
|
||||
signatureS3Key: varchar("signatureS3Key", { length: 500 }),
|
||||
/** URL de la signature */
|
||||
signatureUrl: varchar("signatureUrl", { length: 1000 }),
|
||||
/** Nom du signataire */
|
||||
nomSignataire: varchar("nomSignataire", { length: 255 }),
|
||||
/** Fonction du signataire */
|
||||
fonctionSignataire: varchar("fonctionSignataire", { length: 255 }),
|
||||
/** Texte personnalisable de l'attestation */
|
||||
texteAttestation: text("texteAttestation"),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
|
||||
});
|
||||
|
||||
export type ConfigAttestation = typeof configAttestation.$inferSelect;
|
||||
export type InsertConfigAttestation = typeof configAttestation.$inferInsert;
|
||||
|
||||
Reference in New Issue
Block a user