Checkpoint: Implémentation complète de la fonctionnalité QR code formateur :
- Procédure generateQRCodeFormateur dans routers.ts
- Fonction validerPresenceFormateur dans presenceDb.ts
- Bouton "QR Code Formateur" dans FormateurEmargement.tsx
- Page EmargementFormateurScan.tsx pour le scan du QR code
- Route /emargement-formateur/{token}
- Gestion automatique de la date du jour
- Stockage de la signature sur S3
- Champ qrCodeFormateurToken dans le schéma sequences
Prêt pour déploiement et tests sur le VPS.
This commit is contained in:
@@ -185,3 +185,76 @@ export async function supprimerPresence(presenceId: number) {
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
/**
|
||||
* Valider la présence d'un formateur (par QR code ou manuellement)
|
||||
*/
|
||||
export async function validerPresenceFormateur(params: {
|
||||
formateurId: number;
|
||||
sequenceId: number;
|
||||
dateFormationId: number;
|
||||
periode: "matin" | "apres_midi";
|
||||
modeValidation: "qrcode" | "manuel";
|
||||
commentaire?: string;
|
||||
signatureUrl?: string;
|
||||
signatureS3Key?: string;
|
||||
}) {
|
||||
const db = await getDb();
|
||||
if (!db) throw new Error("Database not available");
|
||||
|
||||
// Récupérer la date de formation
|
||||
const dateFormation = await db
|
||||
.select()
|
||||
.from(datesFormation)
|
||||
.where(eq(datesFormation.id, params.dateFormationId))
|
||||
.limit(1);
|
||||
|
||||
if (dateFormation.length === 0) {
|
||||
throw new Error("Date de formation introuvable");
|
||||
}
|
||||
|
||||
// Vérifier que la date actuelle est le jour de la formation ou après
|
||||
const now = new Date();
|
||||
const dateDebut = new Date(dateFormation[0].dateDebut);
|
||||
|
||||
// Réinitialiser les heures pour comparer uniquement les dates
|
||||
now.setHours(0, 0, 0, 0);
|
||||
dateDebut.setHours(0, 0, 0, 0);
|
||||
|
||||
if (now < dateDebut) {
|
||||
throw new Error("Vous ne pouvez pas émarger avant la date de formation");
|
||||
}
|
||||
|
||||
// Vérifier si la présence existe déjà pour cette période
|
||||
const presenceExistante = await db
|
||||
.select()
|
||||
.from(presences)
|
||||
.where(
|
||||
and(
|
||||
eq(presences.formateurId, params.formateurId),
|
||||
eq(presences.dateFormationId, params.dateFormationId),
|
||||
eq(presences.periode, params.periode),
|
||||
eq(presences.typeUtilisateur, 'formateur')
|
||||
)
|
||||
);
|
||||
|
||||
if (presenceExistante.length > 0) {
|
||||
throw new Error(`Présence déjà validée pour ${params.periode === 'matin' ? 'le matin' : 'l\'après-midi'}`);
|
||||
}
|
||||
|
||||
// Créer la présence formateur
|
||||
await db.insert(presences).values({
|
||||
formateurId: params.formateurId,
|
||||
dateFormationId: params.dateFormationId,
|
||||
periode: params.periode,
|
||||
typeUtilisateur: 'formateur',
|
||||
heurePresence: new Date(),
|
||||
modeValidation: params.modeValidation,
|
||||
commentaire: params.commentaire,
|
||||
signatureUrl: params.signatureUrl,
|
||||
signatureS3Key: params.signatureS3Key,
|
||||
dateSigned: params.signatureUrl ? new Date() : undefined,
|
||||
});
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user