/* eslint-disable no-console */ import { PrismaClient, ModelCategory } from '@prisma/client'; const prisma = new PrismaClient(); // --------- Helpers ----------------------------------------------------------- async function findOrCreateModelType(params: { code: string; name: string; category: ModelCategory; description?: string | null; notes?: string | null; }) { const { code, name, category, description = null, notes = null } = params; const existing = await prisma.modelType.findUnique({ where: { code } }).catch(() => null); if (existing) return existing; return prisma.modelType.create({ data: { code, name, category, description, notes }, }); } async function findOrCreateComposantModel(params: { code: string; name: string; typeCode: string; // ModelType (category: COMPONENT) manufacturerName?: string | null; description?: string | null; }) { const { code, name, typeCode, manufacturerName = null, description = null } = params; const existing = await prisma.composantModel.findUnique({ where: { code } }).catch(() => null); if (existing) return existing; const type = await prisma.modelType.findUnique({ where: { code: typeCode } }); if (!type) throw new Error(`ComposantModel: type '${typeCode}' introuvable`); const manufacturer = manufacturerName ? await prisma.constructeur.upsert({ where: { name: manufacturerName }, create: { name: manufacturerName }, update: {}, }) : null; return prisma.composantModel.create({ data: { code, name, description, typeComposant: { connect: { id: type.id } }, ...(manufacturer ? { constructeur: { connect: { id: manufacturer.id } } } : {}), }, }); } async function findOrCreatePieceModel(params: { code: string; name: string; typeCode: string; // ModelType (category: PIECE) manufacturerName?: string | null; description?: string | null; }) { const { code, name, typeCode, manufacturerName = null, description = null } = params; const existing = await prisma.pieceModel.findUnique({ where: { code } }).catch(() => null); if (existing) return existing; const type = await prisma.modelType.findUnique({ where: { code: typeCode } }); if (!type) throw new Error(`PieceModel: type '${typeCode}' introuvable`); const manufacturer = manufacturerName ? await prisma.constructeur.upsert({ where: { name: manufacturerName }, create: { name: manufacturerName }, update: {}, }) : null; return prisma.pieceModel.create({ data: { code, name, description, typePiece: { connect: { id: type.id } }, ...(manufacturer ? { constructeur: { connect: { id: manufacturer.id } } } : {}), }, }); } async function upsertTypeMachine(params: { code: string; name: string; category?: string | null; description?: string | null; }) { const { code, name, category = 'Convoyage', description = null } = params; // Beaucoup de schémas mettent un unique sur name OU code. On essaye les deux. const existingByCode = await prisma.typeMachine.findUnique({ where: { code } }).catch(() => null); if (existingByCode) return existingByCode; const existingByName = await prisma.typeMachine.findUnique({ where: { name } }).catch(() => null); if (existingByName) return existingByName; return prisma.typeMachine.create({ data: { code, name, category, description, }, }); } async function addTypeMachineCustomFields(typeMachineId: string) { // upsert par (typeMachineId, name) si le schéma le permet, sinon find/create const defs = [ { name: 'capacite_t_h', type: 'NUMBER', required: false, options: null }, { name: 'hauteur_m', type: 'NUMBER', required: false, options: null }, { name: 'sens', type: 'SELECT', required: false, options: ['montant', 'descendant'] }, { name: 'vitesse_m_s', type: 'NUMBER', required: false, options: null }, ]; for (const d of defs) { const already = await prisma.customField.findFirst({ where: { name: d.name, typeMachineId }, }); if (!already) { await prisma.customField.create({ data: { name: d.name, type: d.type as any, required: d.required, options: d.options as any, typeMachine: { connect: { id: typeMachineId } }, }, }); } } } async function addRequirements(params: { typeMachineId: string; components: Array<{ label: string; typeCode: string; // ModelType (COMPONENT) minCount?: number; maxCount?: number | null; required?: boolean; allowNewModels?: boolean; }>; pieces: Array<{ label: string; typeCode: string; // ModelType (PIECE) minCount?: number; maxCount?: number | null; required?: boolean; allowNewModels?: boolean; }>; }) { const { typeMachineId, components, pieces } = params; // Composants for (const r of components) { const type = await prisma.modelType.findUnique({ where: { code: r.typeCode } }); if (!type) throw new Error(`Requirement component: type '${r.typeCode}' introuvable`); // Évite les doublons simples par (typeMachineId, typeComposantId, label) const exists = await prisma.typeMachineComponentRequirement.findFirst({ where: { typeMachineId, typeComposantId: type.id, label: r.label, }, }); if (!exists) { await prisma.typeMachineComponentRequirement.create({ data: { typeMachine: { connect: { id: typeMachineId } }, typeComposant: { connect: { id: type.id } }, label: r.label, minCount: r.minCount ?? 0, maxCount: r.maxCount ?? null, required: r.required ?? true, allowNewModels: r.allowNewModels ?? true, }, }); } } // Pièces for (const r of pieces) { const type = await prisma.modelType.findUnique({ where: { code: r.typeCode } }); if (!type) throw new Error(`Requirement piece: type '${r.typeCode}' introuvable`); const exists = await prisma.typeMachinePieceRequirement.findFirst({ where: { typeMachineId, typePieceId: type.id, label: r.label, }, }); if (!exists) { await prisma.typeMachinePieceRequirement.create({ data: { typeMachine: { connect: { id: typeMachineId } }, typePiece: { connect: { id: type.id } }, label: r.label, minCount: r.minCount ?? 0, maxCount: r.maxCount ?? null, required: r.required ?? false, allowNewModels: r.allowNewModels ?? true, }, }); } } } // --------- Seed principal ---------------------------------------------------- async function main() { // 1) Quelques constructeurs de base await prisma.constructeur.upsert({ where: { name: 'SEW' }, update: {}, create: { name: 'SEW' }, }); await prisma.constructeur.upsert({ where: { name: 'NORD' }, update: {}, create: { name: 'NORD' }, }); await prisma.constructeur.upsert({ where: { name: 'SKF' }, update: {}, create: { name: 'SKF' }, }); // 2) Familles (ModelType) // COMPONENT const compTypes = [ { code: 'elev-tete', name: 'Tête', category: ModelCategory.COMPONENT }, { code: 'elev-pied', name: 'Pied', category: ModelCategory.COMPONENT }, { code: 'elev-gaine', name: 'Gaine', category: ModelCategory.COMPONENT }, { code: 'elev-entrainement', name: 'Entraînement', category: ModelCategory.COMPONENT }, { code: 'elev-retour', name: 'Retour', category: ModelCategory.COMPONENT }, { code: 'elev-sangle-chaine', name: 'Sangle / Chaîne', category: ModelCategory.COMPONENT }, { code: 'elev-godets-comp', name: 'Rangée de godets', category: ModelCategory.COMPONENT }, ]; // PIECE const pieceTypes = [ { code: 'roulement', name: 'Roulement', category: ModelCategory.PIECE }, { code: 'courroie', name: 'Courroie', category: ModelCategory.PIECE }, { code: 'visserie', name: 'Visserie', category: ModelCategory.PIECE }, { code: 'joint', name: 'Joint', category: ModelCategory.PIECE }, { code: 'capteur', name: 'Capteur', category: ModelCategory.PIECE }, { code: 'moteur', name: 'Moteur électrique', category: ModelCategory.PIECE }, { code: 'reducteur', name: 'Réducteur', category: ModelCategory.PIECE }, { code: 'godet', name: 'Godet', category: ModelCategory.PIECE }, { code: 'sangle', name: 'Sangle', category: ModelCategory.PIECE }, { code: 'chaine', name: 'Chaîne', category: ModelCategory.PIECE }, ]; for (const t of [...compTypes, ...pieceTypes]) { await findOrCreateModelType(t); } // 3) Modèles (catalogues) // Composants await findOrCreateComposantModel({ code: 'tete-standard-500', name: 'Tête standard 500', typeCode: 'elev-tete', manufacturerName: null, description: 'Sortie latérale, trappe inspection, tambour d’entraînement', }); await findOrCreateComposantModel({ code: 'pied-standard-500', name: 'Pied standard 500', typeCode: 'elev-pied', description: 'Trémie d’alimentation, tambour de retour', }); await findOrCreateComposantModel({ code: 'gaine-1m', name: 'Gaine 1 m', typeCode: 'elev-gaine', }); await findOrCreateComposantModel({ code: 'drive-unit-sew', name: 'Groupe moto-réducteur SEW', typeCode: 'elev-entrainement', manufacturerName: 'SEW', }); await findOrCreateComposantModel({ code: 'belt-assembly', name: 'Ensemble sangle + jonction', typeCode: 'elev-sangle-chaine', }); // Pièces await findOrCreatePieceModel({ code: 'roulement-2208-skf', name: 'Roulement 2208', typeCode: 'roulement', manufacturerName: 'SKF', }); await findOrCreatePieceModel({ code: 'moteur-5-5kw', name: 'Moteur 5.5 kW', typeCode: 'moteur', manufacturerName: 'SEW', }); await findOrCreatePieceModel({ code: 'reducteur-sew-k', name: 'Réducteur K', typeCode: 'reducteur', manufacturerName: 'SEW', }); await findOrCreatePieceModel({ code: 'godet-2l-poly', name: 'Godet 2 L poly', typeCode: 'godet', }); await findOrCreatePieceModel({ code: 'sangle-500mm-ep500', name: 'Sangle 500 mm EP500', typeCode: 'sangle', }); // 4) TypeMachine “Élévateur à godets” const elevType = await upsertTypeMachine({ code: 'elevateur_godets', name: 'Élévateur à godets', category: 'Convoyage', description: 'Élévateur à godets vertical', }); // Champs personnalisés du type await addTypeMachineCustomFields(elevType.id); // Requirements (groupes logiques implicites via label) await addRequirements({ typeMachineId: elevType.id, components: [ { label: 'Tête', typeCode: 'elev-tete', minCount: 1, maxCount: 1, required: true }, { label: 'Pied', typeCode: 'elev-pied', minCount: 1, maxCount: 1, required: true }, { label: 'Gaines', typeCode: 'elev-gaine', minCount: 1, maxCount: null, required: true }, { label: 'Entraînement', typeCode: 'elev-entrainement', minCount: 1, maxCount: 1, required: true, allowNewModels: true }, { label: 'Retour', typeCode: 'elev-retour', minCount: 1, maxCount: 1, required: false }, { label: 'Sangle/Chaîne', typeCode: 'elev-sangle-chaine', minCount: 1, maxCount: 1, required: true }, { label: 'Rangée de godets', typeCode: 'elev-godets-comp', minCount: 1, maxCount: null, required: true }, ], pieces: [ { label: 'Roulements d’arbres', typeCode: 'roulement', minCount: 2, maxCount: null, required: true }, { label: 'Moteur', typeCode: 'moteur', minCount: 1, maxCount: 1, required: true }, { label: 'Réducteur', typeCode: 'reducteur', minCount: 1, maxCount: 1, required: true }, { label: 'Godets', typeCode: 'godet', minCount: 1, maxCount: null, required: true }, { label: 'Sangle (si sangle)', typeCode: 'sangle', minCount: 1, maxCount: 1, required: false }, { label: 'Chaîne (si chaîne)', typeCode: 'chaine', minCount: 1, maxCount: 2, required: false }, { label: 'Capteurs', typeCode: 'capteur', minCount: 0, maxCount: 4, required: false }, { label: 'Visserie', typeCode: 'visserie', minCount: 0, maxCount: null, required: false }, ], }); console.log('✅ Seed terminé.'); } main() .catch((e) => { console.error('❌ Seed error:', e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); });