Files
formation-manager-itinova/drizzle/meta/_journal.json
Manus b64dedc488 Checkpoint: Système d'émargement numérique avec QR code et génération automatique d'attestations :
## Base de données
-  Table `presences` créée (inscriptionId, dateFormationId, heurePresence, modeValidation, validateurId)
-  Colonne `qrCodeToken` ajoutée à la table `sequences`

## Backend
-  Génération de QR code unique par séquence (qrCodeGenerator.ts)
-  Procédures tRPC pour l'émargement (presences.generateQRCode, presences.valider, presences.listBySequence)
-  Fonctions de base de données (presenceDb.ts) pour gérer les présences
-  Génération automatique d'attestation après validation de toutes les présences
-  Intégration avec le service d'attestations existant

## Interface formateur (/formateur/emargement)
-  Sélection de la séquence
-  Génération et affichage du QR code en modal
-  Liste des inscrits avec statut de présence par date
-  Validation manuelle de présence possible
-  Actualisation en temps réel des présences
-  Entrée de menu "Émargement" dans DashboardLayout

## Interface publique (/emargement/:token)
-  Page de scan QR code accessible sans authentification
-  Recherche de l'apprenant par email
-  Sélection de la formation et de la date
-  Validation automatique de la présence via QR code
-  Écrans de confirmation (succès/erreur)
-  Gestion des erreurs (QR invalide, déjà émargé, etc.)

## Génération automatique d'attestations
-  Vérification automatique après chaque validation de présence
-  Génération du PDF d'attestation si toutes les présences sont validées
-  Enregistrement en base de données
-  Upload automatique sur S3

## Dépendances installées
- qrcode (génération de QR codes)
- @types/qrcode (types TypeScript)

Le système est entièrement fonctionnel et prêt à être utilisé par les formateurs et apprenants.
2026-01-11 14:01:22 -05:00

230 lines
4.6 KiB
JSON

{
"version": "7",
"dialect": "mysql",
"entries": [
{
"idx": 0,
"version": "5",
"when": 1762953852020,
"tag": "0000_charming_grey_gargoyle",
"breakpoints": true
},
{
"idx": 1,
"version": "5",
"when": 1762953926304,
"tag": "0001_smooth_warbird",
"breakpoints": true
},
{
"idx": 2,
"version": "5",
"when": 1762957612797,
"tag": "0002_fuzzy_sugar_man",
"breakpoints": true
},
{
"idx": 3,
"version": "5",
"when": 1762958719297,
"tag": "0003_steady_mystique",
"breakpoints": true
},
{
"idx": 4,
"version": "5",
"when": 1763047968048,
"tag": "0004_futuristic_malice",
"breakpoints": true
},
{
"idx": 5,
"version": "5",
"when": 1763050409917,
"tag": "0005_cuddly_bushwacker",
"breakpoints": true
},
{
"idx": 6,
"version": "5",
"when": 1763412717239,
"tag": "0006_lame_madrox",
"breakpoints": true
},
{
"idx": 7,
"version": "5",
"when": 1763414014386,
"tag": "0007_awesome_genesis",
"breakpoints": true
},
{
"idx": 8,
"version": "5",
"when": 1763416801277,
"tag": "0008_jittery_fenris",
"breakpoints": true
},
{
"idx": 9,
"version": "5",
"when": 1763448844826,
"tag": "0009_polite_senator_kelly",
"breakpoints": true
},
{
"idx": 10,
"version": "5",
"when": 1763628773882,
"tag": "0010_aspiring_kitty_pryde",
"breakpoints": true
},
{
"idx": 11,
"version": "5",
"when": 1763630439521,
"tag": "0011_natural_cyclops",
"breakpoints": true
},
{
"idx": 12,
"version": "5",
"when": 1763737191050,
"tag": "0012_dapper_ronan",
"breakpoints": true
},
{
"idx": 13,
"version": "5",
"when": 1763927796862,
"tag": "0013_demonic_trish_tilby",
"breakpoints": true
},
{
"idx": 14,
"version": "5",
"when": 1763933695050,
"tag": "0014_calm_thanos",
"breakpoints": true
},
{
"idx": 15,
"version": "5",
"when": 1764056078540,
"tag": "0015_young_moonstone",
"breakpoints": true
},
{
"idx": 16,
"version": "5",
"when": 1764329348207,
"tag": "0016_romantic_sinister_six",
"breakpoints": true
},
{
"idx": 17,
"version": "5",
"when": 1764540514199,
"tag": "0017_unique_skrulls",
"breakpoints": true
},
{
"idx": 18,
"version": "5",
"when": 1764934995109,
"tag": "0018_smooth_purifiers",
"breakpoints": true
},
{
"idx": 19,
"version": "5",
"when": 1765143202063,
"tag": "0019_unknown_nomad",
"breakpoints": true
},
{
"idx": 20,
"version": "5",
"when": 1765180630803,
"tag": "0020_large_rocket_raccoon",
"breakpoints": true
},
{
"idx": 21,
"version": "5",
"when": 1765183092631,
"tag": "0021_equal_the_fallen",
"breakpoints": true
},
{
"idx": 22,
"version": "5",
"when": 1765828479906,
"tag": "0022_closed_lucky_pierre",
"breakpoints": true
},
{
"idx": 23,
"version": "5",
"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
},
{
"idx": 27,
"version": "5",
"when": 1767799408213,
"tag": "0027_naive_jackal",
"breakpoints": true
},
{
"idx": 28,
"version": "5",
"when": 1767868505577,
"tag": "0028_military_pandemic",
"breakpoints": true
},
{
"idx": 29,
"version": "5",
"when": 1767869539717,
"tag": "0029_classy_warbound",
"breakpoints": true
},
{
"idx": 30,
"version": "5",
"when": 1767877943207,
"tag": "0030_cultured_korg",
"breakpoints": true
},
{
"idx": 31,
"version": "5",
"when": 1768157247820,
"tag": "0031_simple_anthem",
"breakpoints": true
}
]
}