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:
Manus
2026-01-07 10:06:29 -05:00
parent cc3badffa3
commit 023711df92
15 changed files with 6691 additions and 2 deletions

View File

@@ -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;