openapi: 3.1.0 info: title: PolyMPR API version: 2.0.0 description: API de gestion des étudiants, notes, mobilités, stages et administration. servers: - url: / tags: - name: Students - name: Promotions - name: Users - name: Roles - name: Permissions - name: Modules - name: Enseignements - name: UEs - name: UE_Modules - name: Notes - name: Ajustements - name: Mobilités - name: Stages paths: # ── Students ────────────────────────────────────────────── /students/api/students: get: tags: [Students] summary: Liste des étudiants parameters: - $ref: "#/components/parameters/idPromoQuery" responses: "200": description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/Student" post: tags: [Students] summary: Créer un étudiant requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/StudentCreate" responses: "201": description: Créé content: application/json: schema: $ref: "#/components/schemas/Student" /students/api/students/import-csv: post: tags: [Students] summary: Importer des étudiants par CSV requestBody: required: true content: multipart/form-data: schema: type: object required: [file, idPromo] properties: file: type: string format: binary idPromo: type: string responses: "200": description: Résultat de l'import content: application/json: schema: type: object properties: imported: type: integer errors: type: array items: type: object properties: line: type: integer message: type: string /students/api/students/{numEtud}: parameters: - $ref: "#/components/parameters/numEtud" get: tags: [Students] summary: Détail d'un étudiant responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Student" "404": $ref: "#/components/responses/NotFound" put: tags: [Students] summary: Modifier un étudiant requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/StudentCreate" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Student" "404": $ref: "#/components/responses/NotFound" delete: tags: [Students] summary: Supprimer un étudiant (cascade mobilités et stages) responses: "204": description: Supprimé "404": $ref: "#/components/responses/NotFound" # ── Promotions ──────────────────────────────────────────── /students/api/promotions: get: tags: [Promotions] summary: Liste des promotions responses: "200": description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/Promotion" post: tags: [Promotions] summary: Créer une promotion requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PromotionCreate" responses: "201": description: Créé content: application/json: schema: $ref: "#/components/schemas/Promotion" /students/api/promotions/{idPromo}: parameters: - $ref: "#/components/parameters/idPromo" get: tags: [Promotions] summary: Détail d'une promotion responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Promotion" "404": $ref: "#/components/responses/NotFound" put: tags: [Promotions] summary: Modifier une promotion requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/PromotionCreate" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Promotion" "404": $ref: "#/components/responses/NotFound" delete: tags: [Promotions] summary: Supprimer une promotion responses: "204": description: Supprimé "404": $ref: "#/components/responses/NotFound" # ── Users ──────────────────────────────────────────────── /admin/api/users: get: tags: [Users] summary: Liste des utilisateurs responses: "200": description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/User" post: tags: [Users] summary: Créer un utilisateur (employee only) requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UserCreate" responses: "201": description: Créé content: application/json: schema: $ref: "#/components/schemas/User" "403": description: Accès refusé /admin/api/users/{id}: parameters: - name: id in: path required: true schema: type: string get: tags: [Users] summary: Détail d'un utilisateur responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/User" "404": $ref: "#/components/responses/NotFound" put: tags: [Users] summary: Modifier un utilisateur requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UserCreate" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/User" "404": $ref: "#/components/responses/NotFound" delete: tags: [Users] summary: Supprimer un utilisateur responses: "204": description: Supprimé "404": $ref: "#/components/responses/NotFound" # ── Roles ──────────────────────────────────────────────── /admin/api/roles: get: tags: [Roles] summary: Liste des rôles responses: "200": description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/Role" post: tags: [Roles] summary: Créer un rôle requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/RoleCreate" responses: "201": description: Créé content: application/json: schema: $ref: "#/components/schemas/Role" /admin/api/roles/{idRole}: parameters: - name: idRole in: path required: true schema: type: integer get: tags: [Roles] summary: Détail d'un rôle responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Role" "404": $ref: "#/components/responses/NotFound" put: tags: [Roles] summary: Modifier un rôle requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/RoleCreate" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Role" "404": $ref: "#/components/responses/NotFound" delete: tags: [Roles] summary: Supprimer un rôle responses: "204": description: Supprimé "404": $ref: "#/components/responses/NotFound" # ── Permissions ────────────────────────────────────────── /admin/api/permissions: get: tags: [Permissions] summary: Liste des permissions responses: "200": description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/Permission" # ── Modules ─────────────────────────────────────────────── /admin/api/modules: get: tags: [Modules] summary: Liste des modules responses: "200": description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/Module" post: tags: [Modules] summary: Créer un module (employee only) requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/ModuleCreate" responses: "201": description: Créé content: application/json: schema: $ref: "#/components/schemas/Module" "409": description: Un module avec cet identifiant existe déjà /admin/api/modules/{idModule}: parameters: - $ref: "#/components/parameters/idModule" get: tags: [Modules] summary: Détail d'un module responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Module" "404": $ref: "#/components/responses/NotFound" put: tags: [Modules] summary: Modifier un module requestBody: required: true content: application/json: schema: type: object required: [nom] properties: nom: type: string responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Module" "404": $ref: "#/components/responses/NotFound" delete: tags: [Modules] summary: Supprimer un module (cascade notes, ue_modules, enseignements) responses: "204": description: Supprimé "404": $ref: "#/components/responses/NotFound" # ── Enseignements ─────────────────────────────────────── /admin/api/enseignements: get: tags: [Enseignements] summary: Liste des enseignements responses: "200": description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/Enseignement" post: tags: [Enseignements] summary: Créer un enseignement requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/EnseignementCreate" responses: "201": description: Créé content: application/json: schema: $ref: "#/components/schemas/Enseignement" "409": description: Cet enseignement existe déjà /admin/api/enseignements/{idProf}/{idModule}/{idPromo}: parameters: - name: idProf in: path required: true schema: type: string - name: idModule in: path required: true schema: type: string - name: idPromo in: path required: true schema: type: string get: tags: [Enseignements] summary: Détail d'un enseignement responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Enseignement" "404": $ref: "#/components/responses/NotFound" delete: tags: [Enseignements] summary: Supprimer un enseignement responses: "204": description: Supprimé "404": $ref: "#/components/responses/NotFound" # ── UEs ─────────────────────────────────────────────────── /admin/api/ues: get: tags: [UEs] summary: Liste des UEs responses: "200": description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/UE" post: tags: [UEs] summary: Créer une UE requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UECreate" responses: "201": description: Créé content: application/json: schema: $ref: "#/components/schemas/UE" /admin/api/ues/{idUE}: parameters: - $ref: "#/components/parameters/idUE" get: tags: [UEs] summary: Détail d'une UE responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/UE" "404": $ref: "#/components/responses/NotFound" put: tags: [UEs] summary: Modifier une UE requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UECreate" responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/UE" "404": $ref: "#/components/responses/NotFound" delete: tags: [UEs] summary: Supprimer une UE responses: "204": description: Supprimé "404": $ref: "#/components/responses/NotFound" # ── UE_Modules ──────────────────────────────────────────── /admin/api/ue-modules: get: tags: [UE_Modules] summary: Liste des associations UE-Module parameters: - $ref: "#/components/parameters/idPromoQuery" - name: idUE in: query schema: type: integer responses: "200": description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/UEModule" post: tags: [UE_Modules] summary: Associer un module à une UE requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UEModuleCreate" responses: "201": description: Créé content: application/json: schema: $ref: "#/components/schemas/UEModule" /admin/api/ue-modules/{idModule}/{idUE}/{idPromo}: parameters: - name: idModule in: path required: true schema: type: string - name: idUE in: path required: true schema: type: integer - name: idPromo in: path required: true schema: type: string get: tags: [UE_Modules] summary: Détail d'une association UE-Module responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/UEModule" "404": $ref: "#/components/responses/NotFound" put: tags: [UE_Modules] summary: Modifier le coefficient requestBody: required: true content: application/json: schema: type: object required: [coeff] properties: coeff: type: number responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/UEModule" "404": $ref: "#/components/responses/NotFound" delete: tags: [UE_Modules] summary: Supprimer l'association responses: "204": description: Supprimé "404": $ref: "#/components/responses/NotFound" # ── Notes ───────────────────────────────────────────────── /notes/api/notes: get: tags: [Notes] summary: Liste des notes parameters: - name: numEtud in: query schema: type: integer - name: idModule in: query schema: type: string responses: "200": description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/Note" post: tags: [Notes] summary: Créer une note requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/NoteCreate" responses: "201": description: Créé content: application/json: schema: $ref: "#/components/schemas/Note" "409": description: Note déjà existante pour cet étudiant/module /notes/api/notes/import-xlsx: post: tags: [Notes] summary: Importer des notes par fichier XLSX requestBody: required: true content: multipart/form-data: schema: type: object required: [file, idModule] properties: file: type: string format: binary idModule: type: string responses: "200": description: Import réussi content: application/json: schema: type: object properties: imported: type: integer errors: type: array items: type: object properties: line: type: integer student: type: string message: type: string "400": description: Fichier invalide ou données corrompues /notes/api/notes/{numEtud}/{idModule}: parameters: - name: numEtud in: path required: true schema: type: integer - name: idModule in: path required: true schema: type: string get: tags: [Notes] summary: Détail d'une note responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Note" "404": $ref: "#/components/responses/NotFound" put: tags: [Notes] summary: Modifier une note requestBody: required: true content: application/json: schema: type: object required: [note] properties: note: type: number minimum: 0 maximum: 20 responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Note" "404": $ref: "#/components/responses/NotFound" delete: tags: [Notes] summary: Supprimer une note responses: "204": description: Supprimé "404": $ref: "#/components/responses/NotFound" # ── Ajustements ─────────────────────────────────────────── /notes/api/ajustements: get: tags: [Ajustements] summary: Liste des ajustements parameters: - name: numEtud in: query schema: type: integer - name: idUE in: query schema: type: integer responses: "200": description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/Ajustement" post: tags: [Ajustements] summary: Créer un ajustement requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/AjustementCreate" responses: "201": description: Créé content: application/json: schema: $ref: "#/components/schemas/Ajustement" /notes/api/ajustements/{numEtud}/{idUE}: parameters: - name: numEtud in: path required: true schema: type: integer - name: idUE in: path required: true schema: type: integer get: tags: [Ajustements] summary: Détail d'un ajustement responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Ajustement" "404": $ref: "#/components/responses/NotFound" put: tags: [Ajustements] summary: Modifier un ajustement requestBody: required: true content: application/json: schema: type: object required: [valeur] properties: valeur: type: number responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Ajustement" "404": $ref: "#/components/responses/NotFound" delete: tags: [Ajustements] summary: Supprimer un ajustement responses: "204": description: Supprimé "404": $ref: "#/components/responses/NotFound" # ── Mobilités ───────────────────────────────────────────── /mobility/api/mobilites: get: tags: [Mobilités] summary: Liste des mobilités parameters: - name: numEtud in: query schema: type: integer responses: "200": description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/Mobilite" post: tags: [Mobilités] summary: Créer une mobilité description: > Les étudiants ne peuvent pas définir idStage ni changer le status (reste contracts_received). Les mobilités liées à un stage sont automatiquement validées. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/MobiliteCreate" responses: "201": description: Créé content: application/json: schema: $ref: "#/components/schemas/Mobilite" "400": description: Champs requis manquants ou invalides /mobility/api/mobilites/{idMob}: parameters: - name: idMob in: path required: true schema: type: integer get: tags: [Mobilités] summary: Détail d'une mobilité responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Mobilite" "404": $ref: "#/components/responses/NotFound" put: tags: [Mobilités] summary: Modifier une mobilité (employee only) requestBody: required: true content: application/json: schema: type: object properties: duree: type: integer minimum: 1 ecole: type: string nullable: true pays: type: string nullable: true status: $ref: "#/components/schemas/MobilityStatus" idStage: type: integer nullable: true responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Mobilite" "403": description: Accès refusé "404": $ref: "#/components/responses/NotFound" delete: tags: [Mobilités] summary: Supprimer une mobilité (employee only, supprime aussi le contrat) responses: "204": description: Supprimé "403": description: Accès refusé "404": $ref: "#/components/responses/NotFound" /mobility/api/mobilites/{idMob}/contrat: parameters: - name: idMob in: path required: true schema: type: integer get: tags: [Mobilités] summary: Télécharger le contrat PDF responses: "200": description: Fichier PDF content: application/pdf: schema: type: string format: binary "404": $ref: "#/components/responses/NotFound" post: tags: [Mobilités] summary: Uploader un contrat PDF requestBody: required: true content: multipart/form-data: schema: type: object required: [contrat] properties: contrat: type: string format: binary description: Fichier PDF du contrat responses: "200": description: Mobilité mise à jour avec le nom du fichier content: application/json: schema: $ref: "#/components/schemas/Mobilite" "400": description: Fichier manquant ou pas un PDF "404": $ref: "#/components/responses/NotFound" delete: tags: [Mobilités] summary: Supprimer le contrat (employee only) responses: "204": description: Contrat supprimé "403": description: Accès refusé "404": $ref: "#/components/responses/NotFound" # ── Stages ──────────────────────────────────────────────── /stages/api/stages: get: tags: [Stages] summary: Liste des stages parameters: - name: numEtud in: query schema: type: integer responses: "200": description: OK content: application/json: schema: type: array items: $ref: "#/components/schemas/Stage" post: tags: [Stages] summary: Créer un stage (employee only) requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/StageCreate" responses: "201": description: Créé content: application/json: schema: $ref: "#/components/schemas/Stage" "400": description: Champs requis manquants "403": description: Accès refusé /stages/api/stages/{idStage}: parameters: - name: idStage in: path required: true schema: type: integer get: tags: [Stages] summary: Détail d'un stage responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Stage" "404": $ref: "#/components/responses/NotFound" put: tags: [Stages] summary: Modifier un stage (employee only, synchronise la durée sur la mobilité liée) requestBody: required: true content: application/json: schema: type: object properties: duree: type: integer minimum: 1 nomEntreprise: type: string mission: type: string nullable: true responses: "200": description: OK content: application/json: schema: $ref: "#/components/schemas/Stage" "403": description: Accès refusé "404": $ref: "#/components/responses/NotFound" delete: tags: [Stages] summary: Supprimer un stage (employee only, cascade mobilités liées) responses: "204": description: Supprimé "403": description: Accès refusé "404": $ref: "#/components/responses/NotFound" # ── Components ──────────────────────────────────────────────── components: parameters: numEtud: name: numEtud in: path required: true schema: type: integer example: 21212006 idPromo: name: idPromo in: path required: true schema: type: string example: 4AFISE25/26 idPromoQuery: name: idPromo in: query schema: type: string example: 4AFISE25/26 idModule: name: idModule in: path required: true schema: type: string idUE: name: idUE in: path required: true schema: type: integer responses: NotFound: description: Ressource introuvable content: application/json: schema: type: object properties: error: type: string schemas: # ── Student ── Student: type: object properties: numEtud: type: integer nom: type: string prenom: type: string idPromo: type: string StudentCreate: type: object required: [numEtud, nom, prenom, idPromo] properties: numEtud: type: integer nom: type: string prenom: type: string idPromo: type: string # ── Promotion ── Promotion: type: object properties: id: type: string annee: type: string PromotionCreate: type: object required: [id, annee] properties: id: type: string annee: type: string # ── User ── User: type: object properties: id: type: string nom: type: string prenom: type: string idRole: type: integer nullable: true UserCreate: type: object required: [id, nom, prenom] properties: id: type: string nom: type: string prenom: type: string idRole: type: integer # ── Role ── Role: type: object properties: id: type: integer nom: type: string RoleCreate: type: object required: [nom] properties: nom: type: string # ── Permission ── Permission: type: object properties: id: type: string nom: type: string # ── Module ── Module: type: object properties: id: type: string nom: type: string ModuleCreate: type: object required: [id, nom] properties: id: type: string nom: type: string # ── Enseignement ── Enseignement: type: object properties: idProf: type: string idModule: type: string idPromo: type: string EnseignementCreate: type: object required: [idProf, idModule, idPromo] properties: idProf: type: string idModule: type: string idPromo: type: string # ── UE ── UE: type: object properties: id: type: integer nom: type: string UECreate: type: object required: [nom] properties: nom: type: string # ── UE_Module ── UEModule: type: object properties: idModule: type: string idUE: type: integer idPromo: type: string coeff: type: number UEModuleCreate: type: object required: [idModule, idUE, idPromo, coeff] properties: idModule: type: string idUE: type: integer idPromo: type: string coeff: type: number # ── Note ── Note: type: object properties: numEtud: type: integer idModule: type: string note: type: number minimum: 0 maximum: 20 NoteCreate: type: object required: [numEtud, idModule, note] properties: numEtud: type: integer idModule: type: string note: type: number minimum: 0 maximum: 20 # ── Ajustement ── Ajustement: type: object properties: numEtud: type: integer idUE: type: integer valeur: type: number AjustementCreate: type: object required: [numEtud, idUE, valeur] properties: numEtud: type: integer idUE: type: integer valeur: type: number # ── Mobilité ── MobilityStatus: type: string enum: [contracts_received, under_revision, done, validated, canceled] Mobilite: type: object properties: id: type: integer numEtud: type: integer duree: type: integer contratMob: type: string nullable: true ecole: type: string nullable: true pays: type: string nullable: true status: $ref: "#/components/schemas/MobilityStatus" idStage: type: integer nullable: true MobiliteCreate: type: object required: [numEtud, duree] properties: numEtud: type: integer duree: type: integer minimum: 1 ecole: type: string pays: type: string status: $ref: "#/components/schemas/MobilityStatus" idStage: type: integer # ── Stage ── Stage: type: object properties: id: type: integer numEtud: type: integer duree: type: integer nomEntreprise: type: string mission: type: string nullable: true StageCreate: type: object required: [numEtud, duree, nomEntreprise] properties: numEtud: type: integer duree: type: integer minimum: 1 nomEntreprise: type: string mission: type: string