Checkpoint: Correction de l'erreur "No procedure found on path formateurs.create" en ajoutant le routeur formateurs complet avec les procédures list, getById, create, update et delete, ainsi que les fonctions de base de données correspondantes

This commit is contained in:
Manus Sandbox
2025-11-20 03:57:35 -05:00
parent 89cc7db497
commit 7149458bb8
7 changed files with 938 additions and 1 deletions

View File

@@ -0,0 +1,7 @@
CREATE TABLE `formateurs` (
`id` int AUTO_INCREMENT NOT NULL,
`nom` varchar(255) NOT NULL,
`createdAt` timestamp NOT NULL DEFAULT (now()),
`updatedAt` timestamp NOT NULL DEFAULT (now()) ON UPDATE CURRENT_TIMESTAMP,
CONSTRAINT `formateurs_id` PRIMARY KEY(`id`)
);

View File

@@ -0,0 +1,827 @@
{
"version": "5",
"dialect": "mysql",
"id": "8f8379ca-fd36-48b1-abf9-4b53c2877ad8",
"prevId": "a099e856-0b0c-430d-8160-ca950c994fe5",
"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": {}
},
"datesFormation": {
"name": "datesFormation",
"columns": {
"id": {
"name": "id",
"type": "int",
"primaryKey": false,
"notNull": true,
"autoincrement": true
},
"sequenceId": {
"name": "sequenceId",
"type": "int",
"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
},
"ordre": {
"name": "ordre",
"type": "int",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(now())"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {
"datesFormation_id": {
"name": "datesFormation_id",
"columns": [
"id"
]
}
},
"uniqueConstraints": {},
"checkConstraint": {}
},
"emailConfig": {
"name": "emailConfig",
"columns": {
"id": {
"name": "id",
"type": "int",
"primaryKey": false,
"notNull": true,
"autoincrement": true
},
"provider": {
"name": "provider",
"type": "varchar(50)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'resend'"
},
"apiKey": {
"name": "apiKey",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"fromEmail": {
"name": "fromEmail",
"type": "varchar(320)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"fromName": {
"name": "fromName",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'Formation Manager Itinova'"
},
"mode": {
"name": "mode",
"type": "enum('simulation','production')",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'simulation'"
},
"domainVerified": {
"name": "domainVerified",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": false
},
"active": {
"name": "active",
"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": {
"emailConfig_id": {
"name": "emailConfig_id",
"columns": [
"id"
]
}
},
"uniqueConstraints": {},
"checkConstraint": {}
},
"emailTemplates": {
"name": "emailTemplates",
"columns": {
"id": {
"name": "id",
"type": "int",
"primaryKey": false,
"notNull": true,
"autoincrement": true
},
"type": {
"name": "type",
"type": "varchar(50)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"logoUrl": {
"name": "logoUrl",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"primaryColor": {
"name": "primaryColor",
"type": "varchar(7)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'#2563eb'"
},
"headerBgColor": {
"name": "headerBgColor",
"type": "varchar(7)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'#2563eb'"
},
"headerTextColor": {
"name": "headerTextColor",
"type": "varchar(7)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'#ffffff'"
},
"headerTitle": {
"name": "headerTitle",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "'Formation Manager Itinova'"
},
"footerText": {
"name": "footerText",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"active": {
"name": "active",
"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": {
"emailTemplates_id": {
"name": "emailTemplates_id",
"columns": [
"id"
]
}
},
"uniqueConstraints": {
"emailTemplates_type_unique": {
"name": "emailTemplates_type_unique",
"columns": [
"type"
]
}
},
"checkConstraint": {}
},
"formateurs": {
"name": "formateurs",
"columns": {
"id": {
"name": "id",
"type": "int",
"primaryKey": false,
"notNull": true,
"autoincrement": true
},
"nom": {
"name": "nom",
"type": "varchar(255)",
"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": {
"formateurs_id": {
"name": "formateurs_id",
"columns": [
"id"
]
}
},
"uniqueConstraints": {},
"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
},
"sequenceId": {
"name": "sequenceId",
"type": "int",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"statut": {
"name": "statut",
"type": "enum('confirmee','liste_attente','annulee')",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"dateInscription": {
"name": "dateInscription",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(now())"
},
"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": {},
"checkConstraint": {}
},
"passwordResetTokens": {
"name": "passwordResetTokens",
"columns": {
"id": {
"name": "id",
"type": "int",
"primaryKey": false,
"notNull": true,
"autoincrement": true
},
"userId": {
"name": "userId",
"type": "int",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"token": {
"name": "token",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"expiresAt": {
"name": "expiresAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"used": {
"name": "used",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": false
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(now())"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {
"passwordResetTokens_id": {
"name": "passwordResetTokens_id",
"columns": [
"id"
]
}
},
"uniqueConstraints": {
"passwordResetTokens_token_unique": {
"name": "passwordResetTokens_token_unique",
"columns": [
"token"
]
}
},
"checkConstraint": {}
},
"sequences": {
"name": "sequences",
"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
},
"lieu": {
"name": "lieu",
"type": "varchar(500)",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"publicCible": {
"name": "publicCible",
"type": "enum('directeur','chef_service','autre')",
"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": {
"sequences_id": {
"name": "sequences_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'"
},
"isActive": {
"name": "isActive",
"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())"
},
"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": {}
}
}

View File

@@ -71,6 +71,13 @@
"when": 1763448844826, "when": 1763448844826,
"tag": "0009_polite_senator_kelly", "tag": "0009_polite_senator_kelly",
"breakpoints": true "breakpoints": true
},
{
"idx": 10,
"version": "5",
"when": 1763628773882,
"tag": "0010_aspiring_kitty_pryde",
"breakpoints": true
} }
] ]
} }

View File

@@ -198,3 +198,18 @@ export const emailConfig = mysqlTable("emailConfig", {
export type EmailConfig = typeof emailConfig.$inferSelect; export type EmailConfig = typeof emailConfig.$inferSelect;
export type InsertEmailConfig = typeof emailConfig.$inferInsert; export type InsertEmailConfig = typeof emailConfig.$inferInsert;
/**
* Table des formateurs
* Stocke la liste des formateurs disponibles pour animer les séquences
*/
export const formateurs = mysqlTable("formateurs", {
id: int("id").autoincrement().primaryKey(),
/** Nom complet du formateur */
nom: varchar("nom", { length: 255 }).notNull(),
createdAt: timestamp("createdAt").defaultNow().notNull(),
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
});
export type Formateur = typeof formateurs.$inferSelect;
export type InsertFormateur = typeof formateurs.$inferInsert;

View File

@@ -23,7 +23,10 @@ import {
Apprenant, Apprenant,
Formation, Formation,
EmailTemplate, EmailTemplate,
InsertEmailTemplate InsertEmailTemplate,
formateurs,
InsertFormateur,
Formateur
} from "../drizzle/schema"; } from "../drizzle/schema";
import { ENV } from './_core/env'; import { ENV } from './_core/env';
@@ -674,3 +677,43 @@ export async function updateEmailConfig(id: number, data: Partial<InsertEmailCon
}) })
.where(eq(emailConfig.id, id)); .where(eq(emailConfig.id, id));
} }
// ==================== FORMATEURS ====================
export async function createFormateur(data: InsertFormateur) {
const db = await getDb();
if (!db) throw new Error("Database not available");
const result = await db.insert(formateurs).values(data);
return result;
}
export async function getFormateurs() {
const db = await getDb();
if (!db) return [];
return await db.select().from(formateurs);
}
export async function getFormateurById(id: number): Promise<Formateur | undefined> {
const db = await getDb();
if (!db) return undefined;
const result = await db.select().from(formateurs).where(eq(formateurs.id, id)).limit(1);
return result.length > 0 ? result[0] : undefined;
}
export async function updateFormateur(id: number, data: Partial<InsertFormateur>) {
const db = await getDb();
if (!db) throw new Error("Database not available");
await db.update(formateurs).set(data).where(eq(formateurs.id, id));
}
export async function deleteFormateur(id: number) {
const db = await getDb();
if (!db) throw new Error("Database not available");
await db.delete(formateurs).where(eq(formateurs.id, id));
}

View File

@@ -116,6 +116,38 @@ export const appRouter = router({
}), }),
}), }),
// ===== FORMATEURS =====
formateurs: router({
list: adminProcedure.query(async () => {
return db.getFormateurs();
}),
getById: adminProcedure.input(z.object({ id: z.number() })).query(async ({ input }) => {
return db.getFormateurById(input.id);
}),
create: adminProcedure.input(z.object({
nom: z.string().min(1),
})).mutation(async ({ input }) => {
await db.createFormateur(input);
return { success: true };
}),
update: adminProcedure.input(z.object({
id: z.number(),
nom: z.string().min(1).optional(),
})).mutation(async ({ input }) => {
const { id, ...data } = input;
await db.updateFormateur(id, data);
return { success: true };
}),
delete: adminProcedure.input(z.object({ id: z.number() })).mutation(async ({ input }) => {
await db.deleteFormateur(input.id);
return { success: true };
}),
}),
// ===== SÉQUENCES ===== // ===== SÉQUENCES =====
sequences: router({ sequences: router({
list: adminProcedure.query(async () => { list: adminProcedure.query(async () => {

View File

@@ -338,3 +338,9 @@
- [x] Vérifier les utilisateurs existants dans la base de données - [x] Vérifier les utilisateurs existants dans la base de données
- [x] Supprimer tous les utilisateurs sauf les 4 spécifiés (IDs: 1110110, 2010001, 2040001, 2070001) - [x] Supprimer tous les utilisateurs sauf les 4 spécifiés (IDs: 1110110, 2010001, 2040001, 2070001)
- [x] Vérifier que la suppression a réussi - [x] Vérifier que la suppression a réussi
## Correction erreur formateurs.create
- [x] Identifier le code qui appelle formateurs.create
- [x] Ajouter la procédure formateurs.create manquante dans le routeur
- [x] Tester la correction