From 20490a05c54d09f175254ff4df930a752f3393d0 Mon Sep 17 00:00:00 2001 From: SaidSoighiri94 Date: Fri, 19 Jun 2026 11:38:40 +0200 Subject: [PATCH] feat(backend): add GET /api/mes-emprunts endpoint --- .../src/controllers/emprunt.controller.ts | 13 ++++++++++++ .../src/repositories/emprunt.repository.ts | 20 +++++++++++++++++++ eme-backend/src/routes/emprunt.routes.ts | 6 ++++++ eme-backend/src/routes/index.ts | 2 ++ eme-backend/src/services/emprunt.service.ts | 7 +++++++ review.md | 8 +++++++- 6 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 eme-backend/src/controllers/emprunt.controller.ts create mode 100644 eme-backend/src/repositories/emprunt.repository.ts create mode 100644 eme-backend/src/routes/emprunt.routes.ts create mode 100644 eme-backend/src/services/emprunt.service.ts diff --git a/eme-backend/src/controllers/emprunt.controller.ts b/eme-backend/src/controllers/emprunt.controller.ts new file mode 100644 index 0000000..05f439e --- /dev/null +++ b/eme-backend/src/controllers/emprunt.controller.ts @@ -0,0 +1,13 @@ +import { Request, Response } from 'express'; +import { AppError } from '../errors/app-error'; +import { listerMesEmpruntsEnCours } from '../services/emprunt.service'; + +export async function getMesEmprunts(req: Request, res: Response): Promise { + const user = req.user; + if (!user) { + throw new AppError(401, 'Authentification requise'); + } + + const emprunts = await listerMesEmpruntsEnCours(user.id); + res.json({ data: emprunts }); +} diff --git a/eme-backend/src/repositories/emprunt.repository.ts b/eme-backend/src/repositories/emprunt.repository.ts new file mode 100644 index 0000000..67f158f --- /dev/null +++ b/eme-backend/src/repositories/emprunt.repository.ts @@ -0,0 +1,20 @@ +import { Prisma } from '@prisma/client'; +import { prisma } from '../db/prisma'; +import { StatutEmprunt } from '../models/enums'; + +export type EmpruntAvecMateriel = Prisma.EmpruntGetPayload<{ + include: { materiel: { include: { categorie: true } } }; +}>; + +const STATUTS_EN_COURS: StatutEmprunt[] = ['EN_COURS', 'EN_RETARD']; + +export function findEnCoursParUtilisateur(utilisateurId: number): Promise { + return prisma.emprunt.findMany({ + where: { + utilisateurId, + statut: { in: STATUTS_EN_COURS }, + }, + include: { materiel: { include: { categorie: true } } }, + orderBy: { dateRetourPrevue: 'asc' }, + }); +} diff --git a/eme-backend/src/routes/emprunt.routes.ts b/eme-backend/src/routes/emprunt.routes.ts new file mode 100644 index 0000000..7891b85 --- /dev/null +++ b/eme-backend/src/routes/emprunt.routes.ts @@ -0,0 +1,6 @@ +import { Router } from 'express'; +import { getMesEmprunts } from '../controllers/emprunt.controller'; + +export const empruntRoutes: Router = Router(); + +empruntRoutes.get('/', getMesEmprunts); diff --git a/eme-backend/src/routes/index.ts b/eme-backend/src/routes/index.ts index 3d9e8ca..22203b0 100644 --- a/eme-backend/src/routes/index.ts +++ b/eme-backend/src/routes/index.ts @@ -1,8 +1,10 @@ import { Router } from 'express'; import { currentUser } from '../middlewares/current-user'; import { materielRoutes } from './materiel.routes'; +import { empruntRoutes } from './emprunt.routes'; export const apiRouter: Router = Router(); apiRouter.use(currentUser); apiRouter.use('/materiels', materielRoutes); +apiRouter.use('/mes-emprunts', empruntRoutes); diff --git a/eme-backend/src/services/emprunt.service.ts b/eme-backend/src/services/emprunt.service.ts new file mode 100644 index 0000000..08751c2 --- /dev/null +++ b/eme-backend/src/services/emprunt.service.ts @@ -0,0 +1,7 @@ +import { findEnCoursParUtilisateur, EmpruntAvecMateriel } from '../repositories/emprunt.repository'; + +/* RG15 : un étudiant ne consulte que ses propres emprunts, et uniquement ceux + non encore restitués (en cours ou en retard). */ +export function listerMesEmpruntsEnCours(utilisateurId: number): Promise { + return findEnCoursParUtilisateur(utilisateurId); +} diff --git a/review.md b/review.md index c2fdde7..c38a69f 100644 --- a/review.md +++ b/review.md @@ -125,6 +125,12 @@ En terminal interactif (VS Code), `migrate dev` fonctionne normalement (taper `y - Format de réponse standardisé : `{ "data": ... }` (cohérent avec `{ "error": ... }`). - Vérifié au runtime : 401 sans en-tête / utilisateur inconnu, 200 avec les disponibles du campus, filtres OK, 400 sur `categorieId` invalide. +### Étape 15 — Block 4 : endpoint "mes emprunts en cours" +- Endpoint `GET /api/mes-emprunts` : retourne les emprunts non restitués (`EN_COURS`, `EN_RETARD`) de l'utilisateur courant, triés par date de retour prévue, avec le matériel et sa catégorie inclus. +- RG15 : filtrage par `utilisateurId` (chacun ne voit que ses propres emprunts). +- Réutilise l'architecture en couches et l'auth simulée déjà en place. +- Vérifié au runtime : Marie 1 (`EN_COURS`, son `CLOTURE` exclu), Lucas 1 (`EN_RETARD`), Sofia 0 (son `RETOUR_NON_CONFORME` exclu), 401 sans en-tête. + --- ## Dette technique en attente @@ -139,4 +145,4 @@ En terminal interactif (VS Code), `migrate dev` fonctionne normalement (taper `y --- -*Dernière mise à jour : 2026-06-18 — 1er endpoint (catalogue matériel) et architecture en couches en place.* +*Dernière mise à jour : 2026-06-18 — Endpoint "mes emprunts en cours" en place.*