import { eq, sql, and, gte, lte, desc } from "drizzle-orm"; import { getDb } from "./db"; import { sequences, formations, formateurs, datesFormation, inscriptions, apprenants, supportsFormation } from "../drizzle/schema"; /** * Récupère le calendrier des interventions d'un formateur * @param formateurId - ID du formateur * @param dateDebut - Date de début optionnelle * @param dateFin - Date de fin optionnelle */ export async function getCalendrierFormateur(formateurId: number, dateDebut?: Date, dateFin?: Date) { const db = await getDb(); if (!db) return []; const conditions = [eq(sequences.formateurId, formateurId)]; if (dateDebut) { conditions.push(gte(datesFormation.dateDebut, dateDebut)); } if (dateFin) { conditions.push(lte(datesFormation.dateFin, dateFin)); } const results = await db .select({ sequenceId: sequences.id, sequenceNom: sequences.nom, formationId: formations.id, formationNom: formations.nom, dateId: datesFormation.id, dateDebut: datesFormation.dateDebut, dateFin: datesFormation.dateFin, ordre: datesFormation.ordre, lieu: sequences.lieu, nbInscrits: sql`( SELECT COUNT(*) FROM inscriptions WHERE inscriptions.sequenceId = ${sequences.id} AND inscriptions.statut IN ('confirmee', 'liste_attente') )`, }) .from(sequences) .innerJoin(formations, eq(sequences.formationId, formations.id)) .innerJoin(datesFormation, eq(datesFormation.sequenceId, sequences.id)) .where(conditions.length > 0 ? and(...conditions) : undefined) .orderBy(datesFormation.dateDebut); return results; } /** * Récupère la liste des apprenants inscrits à une séquence * @param sequenceId - ID de la séquence */ export async function getApprenantsSequence(sequenceId: number) { const db = await getDb(); if (!db) return []; const results = await db .select({ inscriptionId: inscriptions.id, apprenantId: apprenants.id, nom: apprenants.nom, prenom: apprenants.prenom, email: apprenants.email, fonction: apprenants.fonction, codeEtablissement: apprenants.codeEtablissement, statut: inscriptions.statut, dateInscription: inscriptions.dateInscription, // presenceValidee n'existe pas dans le schéma actuel }) .from(inscriptions) .innerJoin(apprenants, eq(inscriptions.apprenantId, apprenants.id)) .where(eq(inscriptions.sequenceId, sequenceId)) .orderBy(apprenants.nom, apprenants.prenom); return results; } /** * Récupère les supports de formation d'une séquence * @param sequenceId - ID de la séquence */ export async function getSupportsSequence(sequenceId: number) { const db = await getDb(); if (!db) return []; const results = await db .select({ id: supportsFormation.id, nomFichier: supportsFormation.nomFichier, typeFichier: supportsFormation.typeFichier, tailleFichier: supportsFormation.tailleFichier, urlFichier: supportsFormation.urlFichier, description: supportsFormation.description, formateurNom: formateurs.nom, createdAt: supportsFormation.createdAt, }) .from(supportsFormation) .innerJoin(formateurs, eq(supportsFormation.formateurId, formateurs.id)) .where(eq(supportsFormation.sequenceId, sequenceId)) .orderBy(desc(supportsFormation.createdAt)); return results; } /** * Ajoute un support de formation * @param support - Données du support à ajouter */ export async function ajouterSupport(support: { sequenceId: number; formateurId: number; nomFichier: string; typeFichier: string; tailleFichier: number; urlFichier: string; s3Key: string; description?: string; }) { const db = await getDb(); if (!db) throw new Error("Database not available"); const [result] = await db.insert(supportsFormation).values(support); return result; } /** * Supprime un support de formation * @param supportId - ID du support à supprimer * @param formateurId - ID du formateur (pour vérification) */ export async function supprimerSupport(supportId: number, formateurId: number) { const db = await getDb(); if (!db) throw new Error("Database not available"); // Vérifier que le support appartient bien au formateur const [support] = await db .select() .from(supportsFormation) .where( and( eq(supportsFormation.id, supportId), eq(supportsFormation.formateurId, formateurId) ) ) .limit(1); if (!support) { throw new Error("Support non trouvé ou non autorisé"); } await db.delete(supportsFormation).where(eq(supportsFormation.id, supportId)); return support; // Retourner le support pour récupérer la clé S3 } /** * Valide la présence d'un apprenant * @param inscriptionId - ID de l'inscription * @param present - true si présent, false sinon */ export async function validerPresence(inscriptionId: number, present: boolean) { const db = await getDb(); if (!db) throw new Error("Database not available"); await db .update(inscriptions) .set({ statut: present ? 'confirmee' : 'annulee' }) .where(eq(inscriptions.id, inscriptionId)); } /** * Récupère l'historique des formations d'un formateur * @param formateurId - ID du formateur * @param limit - Nombre de résultats à retourner (par défaut 50) */ export async function getHistoriqueFormateur(formateurId: number, limit: number = 50) { const db = await getDb(); if (!db) return []; const results = await db .select({ sequenceId: sequences.id, sequenceNom: sequences.nom, formationNom: formations.nom, dateDebut: sql`MIN(${datesFormation.dateDebut})`, dateFin: sql`MAX(${datesFormation.dateFin})`, lieu: sequences.lieu, nbInscrits: sql`( SELECT COUNT(*) FROM inscriptions WHERE inscriptions.sequenceId = ${sequences.id} AND inscriptions.statut IN ('confirmee', 'liste_attente') )`, nbPresents: sql`( SELECT COUNT(*) FROM inscriptions WHERE inscriptions.sequenceId = ${sequences.id} AND inscriptions.statut = 'confirmee' )`, }) .from(sequences) .innerJoin(formations, eq(sequences.formationId, formations.id)) .innerJoin(datesFormation, eq(datesFormation.sequenceId, sequences.id)) .where(eq(sequences.formateurId, formateurId)) .groupBy(sequences.id, sequences.nom, formations.nom, sequences.lieu) .orderBy(desc(sql`MIN(${datesFormation.dateDebut})`)) .limit(limit); return results; } /** * Récupère les détails d'une séquence pour un formateur * @param sequenceId - ID de la séquence * @param formateurId - ID du formateur (pour vérification) */ export async function getDetailSequence(sequenceId: number, formateurId: number) { const db = await getDb(); if (!db) return null; const [result] = await db .select({ id: sequences.id, nom: sequences.nom, formationNom: formations.nom, lieu: sequences.lieu, capaciteMax: sequences.capaciteMax, formateurNom: formateurs.nom, }) .from(sequences) .innerJoin(formations, eq(sequences.formationId, formations.id)) .innerJoin(formateurs, eq(sequences.formateurId, formateurs.id)) .where( and( eq(sequences.id, sequenceId), eq(sequences.formateurId, formateurId) ) ) .limit(1); if (!result) return null; // Récupérer les dates de formation const dates = await db .select({ id: datesFormation.id, dateDebut: datesFormation.dateDebut, dateFin: datesFormation.dateFin, ordre: datesFormation.ordre, }) .from(datesFormation) .where(eq(datesFormation.sequenceId, sequenceId)) .orderBy(datesFormation.dateDebut); return { ...result, dates, }; }