StageFlow — Plateforme de gestion du cycle de stage

LaravelPHPMySQLBladeTailwind CSS· 3 min de lecture

Une plateforme qui traite le stage comme un cycle de vie unique plutôt que comme un empilement de paperasse : une entreprise publie une offre, un étudiant postule, dépose les documents demandés, et l'ensemble se conclut par une soutenance planifiée portant un jury et une note — le tout en enregistrements liés, pas en fichiers éparpillés.

Le problème et les contraintes

L'administration des stages vit d'ordinaire à trois endroits à la fois : un tableur indiquant qui a postulé où, une boîte mail pleine de rapports en pièce jointe, et un calendrier séparé pour les créneaux de soutenance. Rien ne les réconcilie, si bien que l'état réel du dossier d'un étudiant correspond à ce dont se souvient la dernière personne qui l'a manipulé. La contrainte était de représenter tout le parcours dans un seul schéma, où chaque étape est un enregistrement interrogeable et non un fil de mails.

Approche

  • Cinq entités liées portent le domaine : les entreprises possèdent des stages, les stages reçoivent des candidatures, les candidatures mènent à des soutenances, et les documents sont rattachés à l'utilisateur qui les a déposés.
  • Les candidatures portent un status explicite (pending / accepted / rejected) plutôt qu'un état déduit : « où en est ce dossier » a toujours une réponse unique en base.
  • Le rôle est choisi et validé à l'inscription (student / professor / admin), ce qui permet aux mêmes routes de servir des vues différentes sans un système de comptes distinct par public.
  • Des contrôleurs de ressource pour ce qui se consulte (stages, entreprises) et des points d'entrée dédiés aux transitions d'état (/apply, /upload, /defense/schedule) — la lecture et l'avancement dans le cycle ont volontairement des formes différentes.
1..n1..n1..n0..1companiesusersrole: student,professor, admininternshipsdocumentsPOST /uploadowner: userapplicationsPOST /applystatus: pending,accepted, rejecteddefensesPOST /defense/schedulejury, grade

Description complète :

  1. companies → internships (1..n)
  2. users — role: student, — professor, admin → documents — POST /upload — owner: user (1..n)
  3. internships → applications — POST /apply — status: pending, — accepted, rejected (1..n)
  4. applications — POST /apply — status: pending, — accepted, rejected → defenses — POST /defense/schedule — jury, grade (0..1)
Les cinq enregistrements liés, et les endpoints qui font avancer un dossier. Les cardinalités sont sur les flèches ; la route qui crée un enregistrement est écrite dedans.

Compromis faits

Decision

Une soutenance en table à part, liée à la candidature, plutôt qu'en colonnes sur la candidature : garde le créneau, le jury et la note hors de la ligne de candidature et permet à un dossier d'exister légitimement sans soutenance, au prix d'une jointure supplémentaire sur les vues affichant un dossier complet.

Decision

Le rôle comme champ validé sur l'utilisateur plutôt qu'un paquet de permissions : le chemin le plus honnête et le plus rapide vers trois publics nettement séparés, en acceptant que tout besoin plus fin que « étudiant / professeur / admin » devrait être reconstruit sur une vraie couche d'autorisation.

Résultats

Un parcours fonctionnel depuis l'offre de stage publiée jusqu'à la soutenance notée, où chaque étape est un enregistrement persistant avec un propriétaire — la question « quels étudiants doivent encore des documents » devient une requête plutôt qu'un audit de boîte mail.

Ce que je referais différemment

Stocker les membres du jury en relation réelle au lieu d'une chaîne séparée par des virgules dans une seule colonne — la forme actuelle ne peut pas répondre à « dans quels jurys siège ce professeur » sans comparaison de chaînes. Je validerais aussi les documents déposés par type MIME et pas seulement par taille : un plafond de 2 Mo ne dit rien de ce que contient réellement le fichier.