diff --git a/drizzle/0002_fuzzy_sugar_man.sql b/drizzle/0002_fuzzy_sugar_man.sql
new file mode 100644
index 0000000..193d977
--- /dev/null
+++ b/drizzle/0002_fuzzy_sugar_man.sql
@@ -0,0 +1 @@
+ALTER TABLE `apprenants` ADD `fonction` enum('directeur','chef_service','autre') NOT NULL;
\ No newline at end of file
diff --git a/drizzle/meta/0002_snapshot.json b/drizzle/meta/0002_snapshot.json
new file mode 100644
index 0000000..885af4d
--- /dev/null
+++ b/drizzle/meta/0002_snapshot.json
@@ -0,0 +1,480 @@
+{
+ "version": "5",
+ "dialect": "mysql",
+ "id": "c625e855-6929-4091-a755-d300ea81b53a",
+ "prevId": "95d14d84-eb09-4770-af36-02daa58e4a5d",
+ "tables": {
+ "apprenants": {
+ "name": "apprenants",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "nom": {
+ "name": "nom",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "prenom": {
+ "name": "prenom",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(320)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "codeEtablissement": {
+ "name": "codeEtablissement",
+ "type": "varchar(50)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "fonction": {
+ "name": "fonction",
+ "type": "enum('directeur','chef_service','autre')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "apprenants_id": {
+ "name": "apprenants_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {
+ "apprenants_email_unique": {
+ "name": "apprenants_email_unique",
+ "columns": [
+ "email"
+ ]
+ }
+ },
+ "checkConstraint": {}
+ },
+ "formations": {
+ "name": "formations",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "nom": {
+ "name": "nom",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "description": {
+ "name": "description",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "lienUnique": {
+ "name": "lienUnique",
+ "type": "varchar(100)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "actif": {
+ "name": "actif",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": true
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "formations_id": {
+ "name": "formations_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {
+ "formations_lienUnique_unique": {
+ "name": "formations_lienUnique_unique",
+ "columns": [
+ "lienUnique"
+ ]
+ }
+ },
+ "checkConstraint": {}
+ },
+ "inscriptions": {
+ "name": "inscriptions",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "apprenantId": {
+ "name": "apprenantId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "sessionId": {
+ "name": "sessionId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "statut": {
+ "name": "statut",
+ "type": "enum('confirmee','liste_attente','annulee')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'confirmee'"
+ },
+ "dateInscription": {
+ "name": "dateInscription",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "invitationEnvoyee": {
+ "name": "invitationEnvoyee",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": false
+ },
+ "emailConfirmationEnvoye": {
+ "name": "emailConfirmationEnvoye",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": false
+ },
+ "emailTeaserEnvoye": {
+ "name": "emailTeaserEnvoye",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": false
+ },
+ "emailRappelEnvoye": {
+ "name": "emailRappelEnvoye",
+ "type": "boolean",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": false
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "inscriptions_id": {
+ "name": "inscriptions_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {
+ "inscriptions_apprenantId_sessionId_unique": {
+ "name": "inscriptions_apprenantId_sessionId_unique",
+ "columns": [
+ "apprenantId",
+ "sessionId"
+ ]
+ }
+ },
+ "checkConstraint": {}
+ },
+ "sessions": {
+ "name": "sessions",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "formationId": {
+ "name": "formationId",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "nom": {
+ "name": "nom",
+ "type": "varchar(255)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "dateDebut": {
+ "name": "dateDebut",
+ "type": "datetime",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "dateFin": {
+ "name": "dateFin",
+ "type": "datetime",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "lieu": {
+ "name": "lieu",
+ "type": "varchar(500)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "capaciteMax": {
+ "name": "capaciteMax",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": 12
+ },
+ "dateBlocage": {
+ "name": "dateBlocage",
+ "type": "datetime",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "statut": {
+ "name": "statut",
+ "type": "enum('ouverte','bloquee','terminee')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'ouverte'"
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "sessions_id": {
+ "name": "sessions_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {},
+ "checkConstraint": {}
+ },
+ "users": {
+ "name": "users",
+ "columns": {
+ "id": {
+ "name": "id",
+ "type": "int",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": true
+ },
+ "openId": {
+ "name": "openId",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false
+ },
+ "name": {
+ "name": "name",
+ "type": "text",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "email": {
+ "name": "email",
+ "type": "varchar(320)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "loginMethod": {
+ "name": "loginMethod",
+ "type": "varchar(64)",
+ "primaryKey": false,
+ "notNull": false,
+ "autoincrement": false
+ },
+ "role": {
+ "name": "role",
+ "type": "enum('user','admin')",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "'user'"
+ },
+ "createdAt": {
+ "name": "createdAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ },
+ "updatedAt": {
+ "name": "updatedAt",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "onUpdate": true,
+ "default": "(now())"
+ },
+ "lastSignedIn": {
+ "name": "lastSignedIn",
+ "type": "timestamp",
+ "primaryKey": false,
+ "notNull": true,
+ "autoincrement": false,
+ "default": "(now())"
+ }
+ },
+ "indexes": {},
+ "foreignKeys": {},
+ "compositePrimaryKeys": {
+ "users_id": {
+ "name": "users_id",
+ "columns": [
+ "id"
+ ]
+ }
+ },
+ "uniqueConstraints": {
+ "users_openId_unique": {
+ "name": "users_openId_unique",
+ "columns": [
+ "openId"
+ ]
+ }
+ },
+ "checkConstraint": {}
+ }
+ },
+ "views": {},
+ "_meta": {
+ "schemas": {},
+ "tables": {},
+ "columns": {}
+ },
+ "internal": {
+ "tables": {},
+ "indexes": {}
+ }
+}
\ No newline at end of file
diff --git a/drizzle/meta/_journal.json b/drizzle/meta/_journal.json
index af9e749..0e92372 100644
--- a/drizzle/meta/_journal.json
+++ b/drizzle/meta/_journal.json
@@ -15,6 +15,13 @@
"when": 1762953926304,
"tag": "0001_smooth_warbird",
"breakpoints": true
+ },
+ {
+ "idx": 2,
+ "version": "5",
+ "when": 1762957612797,
+ "tag": "0002_fuzzy_sugar_man",
+ "breakpoints": true
}
]
}
\ No newline at end of file
diff --git a/drizzle/schema.ts b/drizzle/schema.ts
index 533b584..131af6a 100644
--- a/drizzle/schema.ts
+++ b/drizzle/schema.ts
@@ -51,6 +51,7 @@ export const apprenants = mysqlTable("apprenants", {
prenom: varchar("prenom", { length: 255 }).notNull(),
email: varchar("email", { length: 320 }).notNull().unique(),
codeEtablissement: varchar("codeEtablissement", { length: 50 }).notNull(),
+ fonction: mysqlEnum("fonction", ["directeur", "chef_service", "autre"]).notNull(),
createdAt: timestamp("createdAt").defaultNow().notNull(),
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});
diff --git a/server/exportService.ts b/server/exportService.ts
index ffc4c99..a576d74 100644
--- a/server/exportService.ts
+++ b/server/exportService.ts
@@ -11,6 +11,7 @@ interface InscriptionExport {
prenom: string;
email: string;
codeEtablissement: string;
+ fonction: string;
statut: string;
dateInscription: Date;
}
@@ -36,6 +37,7 @@ export function generateExcelExport(
'Prénom': i.prenom,
'Email': i.email,
'Code établissement': i.codeEtablissement,
+ 'Fonction': i.fonction === 'directeur' ? 'Directeur' : i.fonction === 'chef_service' ? 'Chef de service' : 'Autre',
'Statut': i.statut === 'confirmee' ? 'Confirmée' : i.statut === 'liste_attente' ? 'Liste d\'attente' : 'Annulée',
'Date d\'inscription': i.dateInscription.toLocaleDateString('fr-FR'),
}));
@@ -122,12 +124,13 @@ export function generatePDFExport(
i.prenom,
i.email,
i.codeEtablissement,
+ i.fonction === 'directeur' ? 'Directeur' : i.fonction === 'chef_service' ? 'Chef de service' : 'Autre',
i.statut === 'confirmee' ? 'Confirmée' : i.statut === 'liste_attente' ? 'Liste d\'attente' : 'Annulée',
]);
autoTable(doc, {
startY: yPos + 10,
- head: [['Nom', 'Prénom', 'Email', 'Code étab.', 'Statut']],
+ head: [['Nom', 'Prénom', 'Email', 'Code étab.', 'Fonction', 'Statut']],
body: tableData,
styles: { fontSize: 9 },
headStyles: { fillColor: [37, 99, 235] },
@@ -173,17 +176,18 @@ export function generateFeuillePresence(
i.nom,
i.prenom,
i.codeEtablissement,
+ i.fonction === 'directeur' ? 'Directeur' : i.fonction === 'chef_service' ? 'Chef de service' : 'Autre',
'', // Colonne signature
]);
autoTable(doc, {
startY: yPos + 10,
- head: [['Nom', 'Prénom', 'Code établissement', 'Signature']],
+ head: [['Nom', 'Prénom', 'Code établissement', 'Fonction', 'Signature']],
body: tableData,
styles: { fontSize: 10, cellPadding: 5 },
headStyles: { fillColor: [37, 99, 235] },
columnStyles: {
- 3: { cellWidth: 40 }, // Largeur pour la colonne signature
+ 4: { cellWidth: 40 }, // Largeur pour la colonne signature
},
});
diff --git a/server/routers.ts b/server/routers.ts
index 2864f43..e63b80c 100644
--- a/server/routers.ts
+++ b/server/routers.ts
@@ -90,6 +90,7 @@ export const appRouter = router({
prenom: z.string().min(1),
email: z.string().email(),
codeEtablissement: z.string().min(1),
+ fonction: z.enum(["directeur", "chef_service", "autre"]),
})).mutation(async ({ input }) => {
await db.createApprenant(input);
return { success: true };
@@ -101,6 +102,7 @@ export const appRouter = router({
prenom: z.string().min(1).optional(),
email: z.string().email().optional(),
codeEtablissement: z.string().min(1).optional(),
+ fonction: z.enum(["directeur", "chef_service", "autre"]).optional(),
})).mutation(async ({ input }) => {
const { id, ...data } = input;
await db.updateApprenant(id, data);
@@ -342,6 +344,7 @@ export const appRouter = router({
prenom: i.apprenant!.prenom,
email: i.apprenant!.email,
codeEtablissement: i.apprenant!.codeEtablissement,
+ fonction: i.apprenant!.fonction,
statut: i.inscription.statut,
dateInscription: new Date(i.inscription.dateInscription),
}));
@@ -375,6 +378,7 @@ export const appRouter = router({
prenom: i.apprenant!.prenom,
email: i.apprenant!.email,
codeEtablissement: i.apprenant!.codeEtablissement,
+ fonction: i.apprenant!.fonction,
statut: i.inscription.statut,
dateInscription: new Date(i.inscription.dateInscription),
}));
@@ -408,6 +412,7 @@ export const appRouter = router({
prenom: i.apprenant!.prenom,
email: i.apprenant!.email,
codeEtablissement: i.apprenant!.codeEtablissement,
+ fonction: i.apprenant!.fonction,
statut: i.inscription.statut,
dateInscription: new Date(i.inscription.dateInscription),
}));
diff --git a/todo.md b/todo.md
index 0f5be5b..293fe3d 100644
--- a/todo.md
+++ b/todo.md
@@ -69,3 +69,8 @@
- [x] Ajouter des filtres de recherche sur la page des apprenants
- [x] Ajouter des filtres complets sur la page de gestion des inscrits (recherche, statut, établissement, tri par date)
+
+- [x] Ajouter le champ "Fonction" (Directeur, Chef de service, Autre) dans la fiche apprenant
+- [x] Mettre à jour le schéma de base de données
+- [x] Mettre à jour les formulaires d'inscription et de gestion
+- [x] Ajouter la fonction dans les exports PDF/Excel