Checkpoint: Application complète de gestion des formations Manager Itinova avec toutes les fonctionnalités : gestion des formations/sessions/apprenants, système d'inscription avec validations, génération d'invitations Outlook, emails automatiques, exports PDF/Excel, et documentation complète.

This commit is contained in:
Manus Sandbox
2025-11-12 08:38:33 -05:00
parent 641200f3a4
commit 0fc35596d9
25 changed files with 4391 additions and 52 deletions

View File

@@ -1,4 +1,4 @@
import { int, mysqlEnum, mysqlTable, text, timestamp, varchar } from "drizzle-orm/mysql-core";
import { int, mysqlEnum, mysqlTable, text, timestamp, varchar, boolean, datetime, unique } from "drizzle-orm/mysql-core";
/**
* Core user table backing auth flow.
@@ -25,4 +25,90 @@ export const users = mysqlTable("users", {
export type User = typeof users.$inferSelect;
export type InsertUser = typeof users.$inferInsert;
// TODO: Add your tables here
/**
* Table des formations (ex: Manager Itinova)
*/
export const formations = mysqlTable("formations", {
id: int("id").autoincrement().primaryKey(),
nom: varchar("nom", { length: 255 }).notNull(),
description: text("description"),
/** Lien unique pour l'inscription à cette formation */
lienUnique: varchar("lienUnique", { length: 100 }).notNull().unique(),
actif: boolean("actif").default(true).notNull(),
createdAt: timestamp("createdAt").defaultNow().notNull(),
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});
export type Formation = typeof formations.$inferSelect;
export type InsertFormation = typeof formations.$inferInsert;
/**
* Table des apprenants
*/
export const apprenants = mysqlTable("apprenants", {
id: int("id").autoincrement().primaryKey(),
nom: varchar("nom", { length: 255 }).notNull(),
prenom: varchar("prenom", { length: 255 }).notNull(),
email: varchar("email", { length: 320 }).notNull().unique(),
codeEtablissement: varchar("codeEtablissement", { length: 50 }).notNull(),
createdAt: timestamp("createdAt").defaultNow().notNull(),
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});
export type Apprenant = typeof apprenants.$inferSelect;
export type InsertApprenant = typeof apprenants.$inferInsert;
/**
* Table des sessions de formation
*/
export const sessions = mysqlTable("sessions", {
id: int("id").autoincrement().primaryKey(),
formationId: int("formationId").notNull(),
nom: varchar("nom", { length: 255 }).notNull(),
/** Date de début de la session */
dateDebut: datetime("dateDebut").notNull(),
/** Date de fin de la session */
dateFin: datetime("dateFin").notNull(),
/** Lieu de la formation */
lieu: varchar("lieu", { length: 500 }).notNull(),
/** Capacité maximale (12 par défaut) */
capaciteMax: int("capaciteMax").default(12).notNull(),
/** Date de blocage des inscriptions (J-15) */
dateBlocage: datetime("dateBlocage").notNull(),
/** Statut de la session */
statut: mysqlEnum("statut", ["ouverte", "bloquee", "terminee"]).default("ouverte").notNull(),
createdAt: timestamp("createdAt").defaultNow().notNull(),
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});
export type Session = typeof sessions.$inferSelect;
export type InsertSession = typeof sessions.$inferInsert;
/**
* Table des inscriptions
*/
export const inscriptions = mysqlTable("inscriptions", {
id: int("id").autoincrement().primaryKey(),
apprenantId: int("apprenantId").notNull(),
sessionId: int("sessionId").notNull(),
/** Statut de l'inscription */
statut: mysqlEnum("statut", ["confirmee", "liste_attente", "annulee"]).default("confirmee").notNull(),
/** Date d'inscription */
dateInscription: timestamp("dateInscription").defaultNow().notNull(),
/** Invitation Outlook envoyée */
invitationEnvoyee: boolean("invitationEnvoyee").default(false).notNull(),
/** Email de confirmation envoyé */
emailConfirmationEnvoye: boolean("emailConfirmationEnvoye").default(false).notNull(),
/** Email teaser envoyé */
emailTeaserEnvoye: boolean("emailTeaserEnvoye").default(false).notNull(),
/** Email rappel J-7 envoyé */
emailRappelEnvoye: boolean("emailRappelEnvoye").default(false).notNull(),
createdAt: timestamp("createdAt").defaultNow().notNull(),
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
}, (table) => ({
// Contrainte d'unicité pour éviter les doubles inscriptions
uniqueInscription: unique().on(table.apprenantId, table.sessionId),
}));
export type Inscription = typeof inscriptions.$inferSelect;
export type InsertInscription = typeof inscriptions.$inferInsert;