add seed data
This commit is contained in:
379
prisma/seed.ts
Normal file
379
prisma/seed.ts
Normal file
@@ -0,0 +1,379 @@
|
||||
/* 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();
|
||||
});
|
||||
Reference in New Issue
Block a user