feat(db): add reference data seed script
This commit is contained in:
@@ -9,7 +9,8 @@
|
|||||||
"dev": "nodemon --exec ts-node src/app.ts",
|
"dev": "nodemon --exec ts-node src/app.ts",
|
||||||
"prisma:generate": "prisma generate",
|
"prisma:generate": "prisma generate",
|
||||||
"prisma:migrate": "prisma migrate dev",
|
"prisma:migrate": "prisma migrate dev",
|
||||||
"prisma:studio": "prisma studio"
|
"prisma:studio": "prisma studio",
|
||||||
|
"seed": "ts-node prisma/seed.ts"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
|
|||||||
@@ -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<void> {
|
||||||
|
// 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);
|
||||||
|
});
|
||||||
@@ -78,6 +78,13 @@ En terminal interactif (VS Code), `migrate dev` fonctionne normalement (taper `y
|
|||||||
- `Notification` et `Historique` sans `updatedAt` (conforme ERD).
|
- `Notification` et `Historique` sans `updatedAt` (conforme ERD).
|
||||||
- ERD mis à jour en miroir.
|
- 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
|
## 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.*
|
||||||
|
|||||||
Reference in New Issue
Block a user