feat(db): enrich demo catalogue fixtures

This commit is contained in:
SaidSoighiri94
2026-07-07 13:47:55 +02:00
parent 98ba359bc5
commit e46ec29543
2 changed files with 198 additions and 7 deletions
+190 -6
View File
@@ -51,14 +51,175 @@ function daysFromNow(n: number): Date {
return d; return d;
} }
async function main(): Promise<void> { interface DemoCategories {
// Idempotence : on ne recharge pas si déjà présent. ordinateur: number;
const witness = await prisma.utilisateur.findUnique({ where: { email: WITNESS_EMAIL } }); video: number;
if (witness) { tablette: number;
console.log('[fixtures] deja chargees — rien a faire'); camera: number;
return; audio: number;
cable: number;
} }
interface DemoMateriel {
nom: string;
marque: string;
modele: string;
reference: string;
numeroInventaire: string;
numeroSerie: string;
etatGeneral: string;
categorieId: number;
accessoires?: string[];
}
async function assurerAccessoire(nom: string, description: string): Promise<number> {
const existant = await prisma.accessoire.findFirst({ where: { nom } });
if (existant) {
return existant.id;
}
const accessoire = await prisma.accessoire.create({ data: { nom, description } });
return accessoire.id;
}
async function assurerMaterielDemo(data: DemoMateriel, campusId: number): Promise<void> {
let materiel = await prisma.materiel.findFirst({ where: { reference: data.reference } });
if (!materiel) {
materiel = await prisma.materiel.create({
data: {
nom: data.nom,
marque: data.marque,
modele: data.modele,
reference: data.reference,
numeroInventaire: data.numeroInventaire,
numeroSerie: data.numeroSerie,
statut: 'DISPONIBLE',
etatGeneral: data.etatGeneral,
categorieId: data.categorieId,
campusId,
},
});
}
for (const nomAccessoire of data.accessoires ?? []) {
const accessoireId = await assurerAccessoire(nomAccessoire, `Accessoire ${nomAccessoire}.`);
const liaison = await prisma.materielAccessoire.findFirst({
where: { materielId: materiel.id, accessoireId },
});
if (!liaison) {
await prisma.materielAccessoire.create({
data: {
materielId: materiel.id,
accessoireId,
quantiteAttendue: 1,
obligatoire: true,
},
});
}
}
}
async function assurerCatalogueDemo(campusId: number, categories: DemoCategories): Promise<void> {
const materiels: DemoMateriel[] = [
{
nom: 'PC Lenovo ThinkPad E14',
marque: 'Lenovo',
modele: 'ThinkPad E14',
reference: 'REF-PC-003',
numeroInventaire: 'INV-PC-003',
numeroSerie: 'SN-LENOVO-003',
etatGeneral: 'Bon etat',
categorieId: categories.ordinateur,
accessoires: ['Chargeur', 'Souris', 'Housse'],
},
{
nom: 'MacBook Air M2',
marque: 'Apple',
modele: 'MacBook Air 13',
reference: 'REF-PC-004',
numeroInventaire: 'INV-PC-004',
numeroSerie: 'SN-MBA-004',
etatGeneral: 'Tres bon etat',
categorieId: categories.ordinateur,
accessoires: ['Chargeur USB-C', 'Housse'],
},
{
nom: 'Microsoft Surface Pro',
marque: 'Microsoft',
modele: 'Surface Pro 9',
reference: 'REF-TAB-002',
numeroInventaire: 'INV-TAB-002',
numeroSerie: 'SN-SURFACE-002',
etatGeneral: 'Bon etat',
categorieId: categories.tablette,
accessoires: ['Clavier Surface', 'Stylet'],
},
{
nom: 'Vidéoprojecteur Epson EB-X49',
marque: 'Epson',
modele: 'EB-X49',
reference: 'REF-VP-002',
numeroInventaire: 'INV-VP-002',
numeroSerie: 'SN-EPSON-002',
etatGeneral: 'Bon etat',
categorieId: categories.video,
accessoires: ['Telecommande', 'Cable HDMI'],
},
{
nom: 'Caméra Canon EOS M50',
marque: 'Canon',
modele: 'EOS M50',
reference: 'REF-CAM-002',
numeroInventaire: 'INV-CAM-002',
numeroSerie: 'SN-CANON-002',
etatGeneral: 'Bon etat',
categorieId: categories.camera,
accessoires: ['Batterie', 'Carte SD', 'Housse'],
},
{
nom: 'Casque Jabra Evolve',
marque: 'Jabra',
modele: 'Evolve 40',
reference: 'REF-AUD-002',
numeroInventaire: 'INV-AUD-002',
numeroSerie: 'SN-JABRA-002',
etatGeneral: 'Bon etat',
categorieId: categories.audio,
},
{
nom: 'Kit câbles HDMI / USB-C',
marque: 'ENSUP',
modele: 'Kit connectique',
reference: 'REF-CAB-001',
numeroInventaire: 'INV-CAB-001',
numeroSerie: 'SN-CABLE-001',
etatGeneral: 'Bon etat',
categorieId: categories.cable,
accessoires: ['Cable HDMI', 'Adaptateur USB-C'],
},
{
nom: 'Enceinte Bluetooth JBL',
marque: 'JBL',
modele: 'Flip 6',
reference: 'REF-AUD-003',
numeroInventaire: 'INV-AUD-003',
numeroSerie: 'SN-JBL-003',
etatGeneral: 'Bon etat',
categorieId: categories.audio,
accessoires: ['Cable USB-C'],
},
];
for (const materiel of materiels) {
await assurerMaterielDemo(materiel, campusId);
}
console.log(`[fixtures] ${materiels.length} materiels de catalogue assures`);
}
async function main(): Promise<void> {
// Références (doivent exister via le seed). // Références (doivent exister via le seed).
const roleEtudiant = required( const roleEtudiant = required(
await prisma.role.findUnique({ where: { code: 'ETUDIANT' } }), await prisma.role.findUnique({ where: { code: 'ETUDIANT' } }),
@@ -100,6 +261,28 @@ async function main(): Promise<void> {
await prisma.categorieMateriel.findFirst({ where: { nom: 'Périphérique audio' } }), await prisma.categorieMateriel.findFirst({ where: { nom: 'Périphérique audio' } }),
'Categorie Périphérique audio manquante', 'Categorie Périphérique audio manquante',
); );
const catCable = required(
await prisma.categorieMateriel.findFirst({ where: { nom: 'Câble / Adaptateur' } }),
'Categorie Câble / Adaptateur manquante',
);
const demoCategories: DemoCategories = {
ordinateur: catOrdi.id,
video: catVideo.id,
tablette: catTablette.id,
camera: catCamera.id,
audio: catAudio.id,
cable: catCable.id,
};
// Idempotence : si les fixtures de base existent déjà, on assure seulement
// les matériels de catalogue ajoutés après coup.
const witness = await prisma.utilisateur.findUnique({ where: { email: WITNESS_EMAIL } });
if (witness) {
await assurerCatalogueDemo(campus.id, demoCategories);
console.log('[fixtures] deja chargees — catalogue demo assure');
return;
}
// Utilisateurs : 3 étudiants (2 info @ensitech.eu, 1 autre @ensup.eu) + 1 responsable. // Utilisateurs : 3 étudiants (2 info @ensitech.eu, 1 autre @ensup.eu) + 1 responsable.
const marie = await prisma.utilisateur.create({ const marie = await prisma.utilisateur.create({
@@ -280,6 +463,7 @@ async function main(): Promise<void> {
{ materielId: camera.id, accessoireId: chargeur.id, quantiteAttendue: 1, obligatoire: true }, { materielId: camera.id, accessoireId: chargeur.id, quantiteAttendue: 1, obligatoire: true },
], ],
}); });
await assurerCatalogueDemo(campus.id, demoCategories);
// Emprunt 1 — EN_COURS (Marie / PC Dell) + checklist de départ. // Emprunt 1 — EN_COURS (Marie / PC Dell) + checklist de départ.
const empruntEnCours = await prisma.emprunt.create({ const empruntEnCours = await prisma.emprunt.create({
+8 -1
View File
@@ -229,6 +229,13 @@ En terminal interactif (VS Code), `migrate dev` fonctionne normalement (taper `y
- Confirmation alimentée par la réponse API (`id`, `dateEmprunt`, matériel renvoyé). - Confirmation alimentée par la réponse API (`id`, `dateEmprunt`, matériel renvoyé).
- Testé sans mutation de données : `POST /api/emprunts` avec checklist vide renvoie bien 400 `La checklist de depart est obligatoire (RG11)`. - Testé sans mutation de données : `POST /api/emprunts` avec checklist vide renvoie bien 400 `La checklist de depart est obligatoire (RG11)`.
### Étape 29 — Données de démonstration catalogue
- Branche dédiée `feat/demo-catalogue-fixtures` créée après merge de `feat/frontend-emprunt-api` dans `develop`.
- `prisma/fixtures.ts` enrichi avec un catalogue de démonstration idempotent : si les fixtures de base existent déjà, le script assure seulement les matériels de catalogue manquants.
- 8 matériels disponibles ajoutés : Lenovo ThinkPad, MacBook Air, Surface Pro, vidéoprojecteur Epson, caméra Canon, casque Jabra, kit câbles HDMI/USB-C, enceinte JBL.
- Accessoires associés assurés sans doublon logique par recherche de nom/référence avant création.
- Vérifié en réel : `npm run fixtures` OK ; `GET /api/materiels` pour Lucas renvoie 10 matériels disponibles.
--- ---
*Dernière mise à jour : 2026-07-07 — Catalogue, détail matériel et création d'emprunt frontend branchés sur l'API backend.* *Dernière mise à jour : 2026-07-07 — Catalogue enrichi, détail matériel et création d'emprunt frontend branchés sur l'API backend.*