Checkpoint: Implémentation complète de la fonctionnalité "Gestion des plans de formations" :
- Schéma DB : 3 nouvelles tables (catalogueFormation, planFormation, planFormationItem) - Backend tRPC : routers catalogue et planFormation (CRUD, import bulk CSV, suggestions, toggle validée Itinova) - Frontend : page Plans de formation (liste par établissement/année, CRUD, soumission/validation) - Frontend : page Détail plan (items, liaison catalogue, suggestions automatiques) - Frontend : page Catalogue de formation (liste, filtres thème/Itinova/OPCO, import CSV, badges) - Menu sidebar : nouvelle section "Plans de formations" avec sous-menus - Tests unitaires : 13 tests (scoring suggestions, validation données, parsing CSV)
This commit is contained in:
@@ -593,3 +593,110 @@ export const historiqueAttestations = mysqlTable("historiqueAttestations", {
|
||||
export type HistoriqueAttestation = typeof historiqueAttestations.$inferSelect;
|
||||
export type InsertHistoriqueAttestation = typeof historiqueAttestations.$inferInsert;
|
||||
|
||||
|
||||
/**
|
||||
* Table du catalogue de formations partagé
|
||||
* Géré par l'équipe Itinova, accessible en lecture à tous les établissements
|
||||
*/
|
||||
export const catalogueFormation = mysqlTable("catalogueFormation", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
/** Intitulé de la formation */
|
||||
intitule: varchar("intitule", { length: 255 }).notNull(),
|
||||
/** Thème principal de la formation */
|
||||
theme: varchar("theme", { length: 255 }),
|
||||
/** Mots-clés pour la recherche et la suggestion automatique (séparés par des virgules) */
|
||||
motsCles: text("motsCles"),
|
||||
/** Durée indicative (ex: "2 jours", "14h") */
|
||||
duree: varchar("duree", { length: 100 }),
|
||||
/** Organisme ou prestataire de formation */
|
||||
prestataire: varchar("prestataire", { length: 255 }),
|
||||
/** Description détaillée de la formation */
|
||||
description: text("description"),
|
||||
/** Objectifs pédagogiques */
|
||||
objectifs: text("objectifs"),
|
||||
/** Public concerné */
|
||||
publicConcerne: varchar("publicConcerne", { length: 255 }),
|
||||
/** Formation qualifiée "Validée Itinova" par l'équipe Itinova */
|
||||
validateeItinova: boolean("validateeItinova").default(false).notNull(),
|
||||
/** Formation éligible au financement OPCO */
|
||||
opcoEligible: boolean("opcoEligible").default(false).notNull(),
|
||||
/** Budget OPCO estimé (en euros) */
|
||||
budgetOpco: decimal("budgetOpco", { precision: 10, scale: 2 }),
|
||||
/** Référence du dossier OPCO */
|
||||
referenceOpco: varchar("referenceOpco", { length: 255 }),
|
||||
/** Source de la formation (import CSV, saisie manuelle, organisme externe) */
|
||||
source: varchar("source", { length: 100 }).default("manuel").notNull(),
|
||||
actif: boolean("actif").default(true).notNull(),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
|
||||
});
|
||||
|
||||
export type CatalogueFormation = typeof catalogueFormation.$inferSelect;
|
||||
export type InsertCatalogueFormation = typeof catalogueFormation.$inferInsert;
|
||||
|
||||
/**
|
||||
* Table des plans de formation par établissement et par année
|
||||
*/
|
||||
export const planFormation = mysqlTable("planFormation", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
/** Code de l'établissement concerné */
|
||||
codeEtablissement: varchar("codeEtablissement", { length: 50 }).notNull(),
|
||||
/** Nom de l'établissement (dénormalisé pour affichage) */
|
||||
nomEtablissement: varchar("nomEtablissement", { length: 255 }),
|
||||
/** Année du plan de formation */
|
||||
annee: int("annee").notNull(),
|
||||
/** Statut du plan (brouillon, soumis, valide, rejete) */
|
||||
statut: mysqlEnum("statut", ["brouillon", "soumis", "valide", "rejete"]).default("brouillon").notNull(),
|
||||
/** Notes générales sur le plan */
|
||||
notes: text("notes"),
|
||||
/** Notes de validation par l'équipe Itinova */
|
||||
notesValidation: text("notesValidation"),
|
||||
/** ID de l'utilisateur qui a créé le plan */
|
||||
creePar: int("creePar"),
|
||||
/** ID de l'utilisateur qui a validé le plan */
|
||||
validePar: int("validePar"),
|
||||
/** Date de soumission */
|
||||
dateSoumission: timestamp("dateSoumission"),
|
||||
/** Date de validation */
|
||||
dateValidation: timestamp("dateValidation"),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
|
||||
});
|
||||
|
||||
export type PlanFormation = typeof planFormation.$inferSelect;
|
||||
export type InsertPlanFormation = typeof planFormation.$inferInsert;
|
||||
|
||||
/**
|
||||
* Table des items (lignes) d'un plan de formation
|
||||
* Chaque item représente une formation souhaitée dans le plan
|
||||
*/
|
||||
export const planFormationItem = mysqlTable("planFormationItem", {
|
||||
id: int("id").autoincrement().primaryKey(),
|
||||
/** ID du plan de formation parent */
|
||||
planId: int("planId").notNull(),
|
||||
/** Intitulé de la formation souhaitée */
|
||||
intitule: varchar("intitule", { length: 255 }).notNull(),
|
||||
/** Durée souhaitée */
|
||||
duree: varchar("duree", { length: 100 }),
|
||||
/** Prestataire souhaité */
|
||||
prestataire: varchar("prestataire", { length: 255 }),
|
||||
/** Public concerné par cette formation */
|
||||
publicConcerne: varchar("publicConcerne", { length: 255 }),
|
||||
/** Nombre de personnes à former */
|
||||
nbPersonnes: int("nbPersonnes"),
|
||||
/** Description ou contexte de la demande */
|
||||
description: text("description"),
|
||||
/** Statut de l'item (en_attente, valide, refuse, suggere) */
|
||||
statut: mysqlEnum("statut", ["en_attente", "valide", "refuse", "suggere"]).default("en_attente").notNull(),
|
||||
/** ID de la formation du catalogue associée (suggestion ou validation) */
|
||||
catalogueFormationId: int("catalogueFormationId"),
|
||||
/** Budget estimé pour cet item */
|
||||
budgetEstime: decimal("budgetEstime", { precision: 10, scale: 2 }),
|
||||
/** Priorité (1 = haute, 2 = moyenne, 3 = basse) */
|
||||
priorite: int("priorite").default(2),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt").defaultNow().onUpdateNow().notNull(),
|
||||
});
|
||||
|
||||
export type PlanFormationItem = typeof planFormationItem.$inferSelect;
|
||||
export type InsertPlanFormationItem = typeof planFormationItem.$inferInsert;
|
||||
|
||||
Reference in New Issue
Block a user