This repository has been archived on 2026-04-01. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
Inventory_backend/scripts/seed-sample-data.ts
2025-10-28 16:37:06 +01:00

587 lines
15 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { PrismaClient, Prisma } from '@prisma/client';
const prisma = new PrismaClient();
type CreatedFields = Record<string, string>;
async function deleteExistingData() {
await prisma.machineComponentLink.deleteMany();
await prisma.machinePieceLink.deleteMany();
await prisma.machine.deleteMany();
await prisma.customFieldValue.deleteMany();
await prisma.composant.deleteMany();
await prisma.piece.deleteMany();
await prisma.modelType.deleteMany({
where: {
code: {
in: [
'hydraulic-pump',
'hydraulic-reservoir',
'cooling-fan',
'cooling-module',
'structural-frame',
'hydraulic-power-unit',
],
},
},
});
}
async function createPieceType(
name: string,
code: string,
description: string,
fields: Array<{
name: string;
type: 'text' | 'number' | 'select' | 'boolean' | 'date';
required?: boolean;
options?: string[];
}>,
skeleton?: Record<string, unknown>,
) {
const type = await prisma.modelType.create({
data: {
name,
code,
category: 'PIECE',
description,
pieceSkeleton: skeleton
? (skeleton as Prisma.InputJsonValue)
: Prisma.JsonNull,
pieceCustomFields: {
create: fields.map((field) => ({
name: field.name,
type: field.type,
required: field.required ?? false,
options: field.options ?? [],
})),
},
},
});
const customFields = await prisma.customField.findMany({
where: { typePieceId: type.id },
});
const fieldMap: CreatedFields = {};
customFields.forEach((field) => {
fieldMap[field.name] = field.id;
});
return { type, fieldMap };
}
async function createComponentType(
name: string,
code: string,
description: string,
fields: Array<{
name: string;
type: 'text' | 'number' | 'select' | 'boolean' | 'date';
required?: boolean;
options?: string[];
}>,
skeleton?: Record<string, unknown>,
) {
const type = await prisma.modelType.create({
data: {
name,
code,
category: 'COMPONENT',
description,
componentSkeleton: skeleton
? (skeleton as Prisma.InputJsonValue)
: Prisma.JsonNull,
customFields: {
create: fields.map((field) => ({
name: field.name,
type: field.type,
required: field.required ?? false,
options: field.options ?? [],
})),
},
},
});
const customFields = await prisma.customField.findMany({
where: { typeComposantId: type.id },
});
const fieldMap: CreatedFields = {};
customFields.forEach((field) => {
fieldMap[field.name] = field.id;
});
return { type, fieldMap };
}
async function createPiece(options: {
name: string;
reference: string;
price: number;
constructeurIds?: string[] | null;
typeId: string;
fieldValues: Record<string, string>;
}) {
const customFields = await prisma.customField.findMany({
where: { typePieceId: options.typeId },
});
const customFieldValues = Object.entries(options.fieldValues).map(
([fieldName, value]) => {
const target = customFields.find((field) => field.name === fieldName);
if (!target) {
throw new Error(
`Custom field "${fieldName}" introuvable pour le type de pièce ${options.typeId}`,
);
}
return {
value,
customFieldId: target.id,
};
},
);
const constructeurIds = Array.isArray(options.constructeurIds)
? Array.from(
new Set(
options.constructeurIds
.filter((value): value is string => typeof value === 'string')
.map((value) => value.trim())
.filter((value) => value.length > 0),
),
)
: [];
const data: any = {
name: options.name,
reference: options.reference,
prix: new Prisma.Decimal(options.price),
typePieceId: options.typeId,
customFieldValues: {
create: customFieldValues,
},
};
if (constructeurIds.length) {
data.constructeurs = {
connect: constructeurIds.map((id) => ({ id })),
};
}
return prisma.piece.create({
data,
});
}
async function createComponent(options: {
name: string;
reference: string;
price: number;
constructeurIds?: string[] | null;
typeId: string;
fieldValues: Record<string, string>;
structure?: Prisma.InputJsonValue;
}) {
const customFields = await prisma.customField.findMany({
where: { typeComposantId: options.typeId },
});
const customFieldValues = Object.entries(options.fieldValues).map(
([fieldName, value]) => {
const target = customFields.find((field) => field.name === fieldName);
if (!target) {
throw new Error(
`Custom field "${fieldName}" introuvable pour le type de composant ${options.typeId}`,
);
}
return {
value,
customFieldId: target.id,
};
},
);
const constructeurIds = Array.isArray(options.constructeurIds)
? Array.from(
new Set(
options.constructeurIds
.filter((value): value is string => typeof value === 'string')
.map((value) => value.trim())
.filter((value) => value.length > 0),
),
)
: [];
const data: any = {
name: options.name,
reference: options.reference,
prix: new Prisma.Decimal(options.price),
typeComposantId: options.typeId,
structure:
options.structure === undefined
? Prisma.JsonNull
: options.structure ?? Prisma.JsonNull,
customFieldValues: {
create: customFieldValues,
},
};
if (constructeurIds.length) {
data.constructeurs = {
connect: constructeurIds.map((id) => ({ id })),
};
}
return prisma.composant.create({
data,
});
}
async function main() {
console.log('Nettoyage des données existantes…');
await deleteExistingData();
console.log('Création des types de pièces…');
const pumpPieceFields: {
name: string;
type: 'text' | 'number' | 'select' | 'boolean' | 'date';
required?: boolean;
options?: string[];
}[] = [
{ name: 'Pression nominale (bar)', type: 'number', required: true },
{ name: 'Débit nominal (L/min)', type: 'number', required: true },
{ name: 'Puissance (kW)', type: 'number', required: true },
{ name: 'Indice de protection', type: 'text' },
{ name: 'Vitesse max (rpm)', type: 'number' },
] as const;
const pumpPieceType = await createPieceType(
'Pompe hydraulique',
'hydraulic-pump',
'Pompes à pistons pour unités hydrauliques',
pumpPieceFields,
{
customFields: pumpPieceFields.map((field) => ({
name: field.name,
key: field.name,
type: field.type,
required: field.required ?? false,
})),
},
);
const reservoirPieceFields: {
name: string;
type: 'text' | 'number' | 'select' | 'boolean' | 'date';
required?: boolean;
options?: string[];
}[] = [
{ name: 'Pression nominale (bar)', type: 'number', required: true },
{ name: 'Débit nominal (L/min)', type: 'number', required: true },
{ name: 'Capacité (L)', type: 'number', required: true },
{ name: 'Type dhuile', type: 'text', required: true },
{ name: 'Filtration', type: 'text' },
] as const;
const reservoirPieceType = await createPieceType(
'Réservoir hydraulique',
'hydraulic-reservoir',
'Réservoirs haute capacité pour fluide hydraulique',
reservoirPieceFields,
{
customFields: reservoirPieceFields.map((field) => ({
name: field.name,
key: field.name,
type: field.type,
required: field.required ?? false,
})),
},
);
const fanPieceFields: {
name: string;
type: 'text' | 'number' | 'select' | 'boolean' | 'date';
required?: boolean;
options?: string[];
}[] = [
{ name: 'Diamètre (mm)', type: 'number', required: true },
{ name: 'Débit air (m³/h)', type: 'number', required: true },
{ name: 'Consommation (A)', type: 'number' },
{ name: 'Tension (V)', type: 'number', required: true },
{ name: 'Niveau sonore (dB)', type: 'number' },
] as const;
const fanPieceType = await createPieceType(
'Ventilateur de refroidissement',
'cooling-fan',
'Ventilateurs axiaux pour modules de refroidissement',
fanPieceFields,
{
customFields: fanPieceFields.map((field) => ({
name: field.name,
key: field.name,
type: field.type,
required: field.required ?? false,
})),
},
);
console.log('Création des pièces…');
const pumpPiece = await createPiece({
name: 'Pompe à pistons PX-300',
reference: 'PX-300',
price: 1850,
typeId: pumpPieceType.type.id,
fieldValues: {
'Pression nominale (bar)': '180',
'Débit nominal (L/min)': '260',
'Puissance (kW)': '45',
'Indice de protection': 'IP55',
'Vitesse max (rpm)': '3200',
},
});
const reservoirPiece = await createPiece({
name: 'Réservoir 120L Inox',
reference: 'RES-120-INX',
price: 720,
typeId: reservoirPieceType.type.id,
fieldValues: {
'Pression nominale (bar)': '12',
'Débit nominal (L/min)': '280',
'Capacité (L)': '120',
'Type dhuile': 'HLP46',
Filtration: '10µ absolu',
},
});
const fanPiece = await createPiece({
name: 'Ventilateur axial VE-450',
reference: 'VE-450',
price: 390,
typeId: fanPieceType.type.id,
fieldValues: {
'Diamètre (mm)': '450',
'Débit air (m³/h)': '5200',
'Consommation (A)': '3.2',
'Tension (V)': '400',
'Niveau sonore (dB)': '68',
},
});
console.log('Création des types de composants…');
const coolingComponentFields: {
name: string;
type: 'text' | 'number' | 'select' | 'boolean' | 'date';
required?: boolean;
options?: string[];
}[] = [
{ name: 'Type de fluide', type: 'text', required: true },
{ name: 'Puissance thermique (kW)', type: 'number', required: true },
{ name: 'Température max (°C)', type: 'number' },
{ name: 'Débit eau (L/min)', type: 'number' },
];
const coolingComponentType = await createComponentType(
'Module de refroidissement',
'cooling-module',
'Modules compacts pour dissipation thermique du circuit hydraulique',
coolingComponentFields,
{
customFields: coolingComponentFields.map((field) => ({
name: field.name,
key: field.name,
type: field.type,
required: field.required ?? false,
})),
pieces: [
{
typePieceId: fanPieceType.type.id,
role: 'Ventilation principale',
},
],
subcomponents: [],
},
);
const frameComponentFields: {
name: string;
type: 'text' | 'number' | 'select' | 'boolean' | 'date';
required?: boolean;
options?: string[];
}[] = [
{ name: 'Matière', type: 'text', required: true },
{ name: 'Charge admissible (kg)', type: 'number', required: true },
{ name: 'Revêtement', type: 'text' },
{ name: 'Points de levage', type: 'number' },
];
const frameComponentType = await createComponentType(
'Châssis structurel',
'structural-frame',
'Châssis mécano-soudé pour unités hydrauliques',
frameComponentFields,
{
customFields: frameComponentFields.map((field) => ({
name: field.name,
key: field.name,
type: field.type,
required: field.required ?? false,
})),
pieces: [],
subcomponents: [],
},
);
const powerUnitComponentFields: {
name: string;
type: 'text' | 'number' | 'select' | 'boolean' | 'date';
required?: boolean;
options?: string[];
}[] = [
{ name: 'Pression service (bar)', type: 'number', required: true },
{ name: 'Débit maxi (L/min)', type: 'number', required: true },
{ name: 'Niveau sonore (dB)', type: 'number' },
{ name: 'Indice de protection', type: 'text' },
];
const powerUnitComponentType = await createComponentType(
'Centrale hydraulique',
'hydraulic-power-unit',
'Unités hydrauliques complètes pour machines industrielles',
powerUnitComponentFields,
{
customFields: powerUnitComponentFields.map((field) => ({
name: field.name,
key: field.name,
type: field.type,
required: field.required ?? false,
})),
pieces: [
{
typePieceId: pumpPieceType.type.id,
role: 'Pompe principale',
},
{
typePieceId: reservoirPieceType.type.id,
role: 'Réservoir dhuile',
},
],
subcomponents: [
{
typeComposantId: coolingComponentType.type.id,
alias: 'Module de refroidissement',
},
{
typeComposantId: frameComponentType.type.id,
alias: 'Châssis structurel',
},
],
},
);
console.log('Création des composants (sous-ensembles)…');
const coolingModule = await createComponent({
name: 'Module de refroidissement AquaCool 50',
reference: 'AC-50',
price: 2450,
typeId: coolingComponentType.type.id,
fieldValues: {
'Type de fluide': 'Huile minérale',
'Puissance thermique (kW)': '35',
'Température max (°C)': '85',
'Débit eau (L/min)': '65',
},
structure: {
path: 'root',
pieces: [
{
path: 'root:piece-0',
definition: {
typePieceId: fanPieceType.type.id,
},
selectedPieceId: fanPiece.id,
},
],
subcomponents: [],
} as Prisma.InputJsonValue,
});
const structuralFrame = await createComponent({
name: 'Châssis structurel XC-800',
reference: 'FRAME-XC800',
price: 1280,
typeId: frameComponentType.type.id,
fieldValues: {
Matière: 'Acier S355',
'Charge admissible (kg)': '1800',
Revêtement: 'Peinture epoxy',
'Points de levage': '4',
},
});
console.log('Création du composant principal…');
await createComponent({
name: 'Centrale hydraulique HX-500',
reference: 'HX-500',
price: 12900,
typeId: powerUnitComponentType.type.id,
fieldValues: {
'Pression service (bar)': '210',
'Débit maxi (L/min)': '320',
'Niveau sonore (dB)': '72',
'Indice de protection': 'IP54',
},
structure: {
path: 'root',
pieces: [
{
path: 'root:piece-0',
definition: {
typePieceId: pumpPieceType.type.id,
},
selectedPieceId: pumpPiece.id,
},
{
path: 'root:piece-1',
definition: {
typePieceId: reservoirPieceType.type.id,
},
selectedPieceId: reservoirPiece.id,
},
],
subcomponents: [
{
path: 'root:sub-0',
definition: {
alias: 'Module de refroidissement',
typeComposantId: coolingComponentType.type.id,
},
selectedComponentId: coolingModule.id,
},
{
path: 'root:sub-1',
definition: {
alias: 'Châssis structurel',
typeComposantId: frameComponentType.type.id,
},
selectedComponentId: structuralFrame.id,
},
],
} as Prisma.InputJsonValue,
});
console.log('Population terminée ✅');
}
main()
.catch((error) => {
console.error(error);
process.exit(1);
})
.finally(async () => {
await prisma.$disconnect();
});