From 2c3a5db05795ee1cbcccb4b27750995170ca0089 Mon Sep 17 00:00:00 2001 From: SaidSoighiri94 Date: Mon, 15 Jun 2026 11:06:08 +0200 Subject: [PATCH] feat(db): add reference data seed script --- eme-backend/package.json | 3 +- eme-backend/prisma/seed.ts | 137 +++++++++++++++++++++++++++++++++++++ review.md | 9 ++- 3 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 eme-backend/prisma/seed.ts diff --git a/eme-backend/package.json b/eme-backend/package.json index 0cb11f9..14f7129 100644 --- a/eme-backend/package.json +++ b/eme-backend/package.json @@ -9,7 +9,8 @@ "dev": "nodemon --exec ts-node src/app.ts", "prisma:generate": "prisma generate", "prisma:migrate": "prisma migrate dev", - "prisma:studio": "prisma studio" + "prisma:studio": "prisma studio", + "seed": "ts-node prisma/seed.ts" }, "keywords": [], "author": "", diff --git a/eme-backend/prisma/seed.ts b/eme-backend/prisma/seed.ts new file mode 100644 index 0000000..9fc87b4 --- /dev/null +++ b/eme-backend/prisma/seed.ts @@ -0,0 +1,137 @@ +import 'dotenv/config'; +import { PrismaClient } from '@prisma/client'; +import { PrismaMssql } from '@prisma/adapter-mssql'; + +// Le seed tourne hors du contexte applicatif : il instancie son propre client +// avec l'adapter MSSQL, en lisant directement les variables d'environnement DB. +function getEnv(name: string): string { + const value = process.env[name]; + + if (!value) { + throw new Error(`Variable d'environnement manquante: ${name}`); + } + + return value; +} + +const adapter = new PrismaMssql({ + server: getEnv('DB_SERVER'), + port: Number(process.env.DB_PORT ?? 1433), + database: getEnv('DB_NAME'), + user: getEnv('DB_USER'), + password: getEnv('DB_PASSWORD'), + options: { + encrypt: true, + trustServerCertificate: true, + }, +}); + +const prisma = new PrismaClient({ adapter }); + +// Données de référence — voir review.md (Étape seeds). +const ROLES = [ + { + code: 'ETUDIANT', + libelle: 'Étudiant', + description: 'Emprunte et restitue du matériel via le poste dédié.', + }, + { + code: 'RESPONSABLE', + libelle: 'Responsable matériel', + description: 'Supervise, gère le stock et traite les anomalies.', + }, +]; + +const CATEGORIES = [ + { nom: 'Ordinateur portable', description: 'Ordinateurs portables pédagogiques.' }, + { nom: 'Vidéoprojecteur', description: 'Vidéoprojecteurs et accessoires de projection.' }, + { nom: 'Tablette', description: 'Tablettes tactiles.' }, + { nom: 'Caméra', description: 'Caméras et matériel de captation vidéo.' }, + { nom: 'Périphérique audio', description: 'Micros, casques et enceintes.' }, + { nom: 'Câble / Adaptateur', description: 'Câbles, adaptateurs et connectique.' }, +]; + +async function main(): Promise { + // Rôles — upsert sur la clé unique `code` (idempotent). + for (const role of ROLES) { + await prisma.role.upsert({ + where: { code: role.code }, + update: { libelle: role.libelle, description: role.description }, + create: role, + }); + } + console.log(`[seed] ${ROLES.length} rôles assurés`); + + // Campus — pas de clé unique : on cherche par nom avant de créer. + const campusNom = 'Campus Saint-Christophe'; + let campus = await prisma.campus.findFirst({ where: { nom: campusNom } }); + + if (!campus) { + campus = await prisma.campus.create({ + data: { + nom: campusNom, + adresse: 'À compléter — Cergy Saint-Christophe', + ville: 'Cergy', + codePostal: '95800', + }, + }); + } + console.log(`[seed] campus "${campus.nom}" (id ${campus.id})`); + + // Salle de prêt — rattachée au campus. + const salleNom = 'Salle de prêt principale'; + let salle = await prisma.sallePret.findFirst({ + where: { nom: salleNom, campusId: campus.id }, + }); + + if (!salle) { + salle = await prisma.sallePret.create({ + data: { + nom: salleNom, + localisation: campusNom, + campusId: campus.id, + }, + }); + } + console.log(`[seed] salle "${salle.nom}" (id ${salle.id})`); + + // Poste d'emprunt — rattaché à la salle, identifié par `identifiantPoste`. + const identifiantPoste = 'POSTE-01'; + let poste = await prisma.posteEmprunt.findFirst({ + where: { identifiantPoste }, + }); + + if (!poste) { + poste = await prisma.posteEmprunt.create({ + data: { + nom: 'Poste 1', + identifiantPoste, + sallePretId: salle.id, + }, + }); + } + console.log(`[seed] poste "${poste.nom}" (${poste.identifiantPoste})`); + + // Catégories de matériel — cherche par nom avant de créer. + for (const categorie of CATEGORIES) { + const existante = await prisma.categorieMateriel.findFirst({ + where: { nom: categorie.nom }, + }); + + if (!existante) { + await prisma.categorieMateriel.create({ data: categorie }); + } + } + console.log(`[seed] ${CATEGORIES.length} catégories assurées`); +} + +main() + .then(async () => { + await prisma.$disconnect(); + console.log('[seed] termine'); + }) + .catch(async (error: unknown) => { + console.error('[seed] echec', error); + await prisma.$disconnect(); + process.exit(1); + }); diff --git a/review.md b/review.md index 3c70cc4..6748881 100644 --- a/review.md +++ b/review.md @@ -78,6 +78,13 @@ En terminal interactif (VS Code), `migrate dev` fonctionne normalement (taper `y - `Notification` et `Historique` sans `updatedAt` (conforme ERD). - ERD mis à jour en miroir. +### Étape 9 — Seeds de référence +- Fichier `prisma/seed.ts` autonome (adapter MSSQL, lecture directe des variables DB), lancé via `npm run seed` (script ajouté au `package.json`). +- Choix `npm run seed` (ts-node) plutôt que `prisma db seed` : l'API de configuration du seed en Prisma 7 (`prisma.config.ts`) n'étant pas confirmée, un script direct est plus fiable. +- Données : 2 rôles (`ETUDIANT`, `RESPONSABLE`), 1 campus (`Campus Saint-Christophe`, Cergy, 95800, adresse provisoire), 1 salle (`Salle de prêt principale`), 1 poste (`POSTE-01`), 6 catégories (Ordinateur portable, Vidéoprojecteur, Tablette, Caméra, Périphérique audio, Câble / Adaptateur). +- Idempotence : `upsert` sur `Role.code` ; `findFirst` avant `create` pour les entités sans clé unique. Relance vérifiée (aucun doublon). +- Incident : le client Prisma était obsolète (ne connaissait que les 4 modèles de référence). Régénéré avec `npx prisma generate` avant le seed. Leçon : après des migrations, régénérer/vérifier le client avant d'exécuter du code qui l'utilise. + --- ## Dette technique en attente @@ -92,4 +99,4 @@ En terminal interactif (VS Code), `migrate dev` fonctionne normalement (taper `y --- -*Dernière mise à jour : 2026-06-15 — Schéma 16/16, fin du Bloc E.* +*Dernière mise à jour : 2026-06-15 — Seeds de référence en place.*