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-industrial-data.ts
2025-10-01 16:12:10 +02:00

1868 lines
54 KiB
TypeScript

import { PrismaClient, Prisma, ModelCategory } from '@prisma/client';
const prisma = new PrismaClient();
type CustomFieldSpec = {
name: string;
type: 'string' | 'number' | 'boolean' | 'date';
required?: boolean;
defaultValue?: string;
options?: string[];
};
type ComponentTypeDefinition = {
code: string;
name: string;
description: string;
customFields: CustomFieldSpec[];
};
type PieceTypeDefinition = {
code: string;
name: string;
description: string;
customFields: CustomFieldSpec[];
};
type PieceModelDefinition = {
code: string;
name: string;
description: string;
typeCode: string;
structure?: Prisma.InputJsonValue;
};
type ComponentModelDefinition = {
code: string;
name: string;
description: string;
typeCode: string;
structure?: Prisma.InputJsonValue;
};
type ConstructeurDefinition = {
key: string;
name: string;
email?: string;
phone?: string;
};
type ComponentPieceInstance = {
name: string;
reference?: string;
prix?: string;
typeCode: string;
modelCode: string;
constructeur?: string;
customValues?: Record<string, string | number | boolean | Date>;
};
type ComponentInstance = {
name: string;
reference?: string;
prix?: string;
typeCode: string;
requirementLabel?: string;
modelCode: string;
constructeur?: string;
customValues?: Record<string, string | number | boolean | Date>;
pieces?: ComponentPieceInstance[];
children?: ComponentInstance[];
};
const componentTypeDefinitions: ComponentTypeDefinition[] = [
{
code: 'bucket-elevator',
name: 'Élévateur à godets',
description:
"Élévateur vertical utilisé pour monter les grains vers les étages supérieurs de l'usine.",
customFields: [
{ name: 'Débit nominal (t/h)', type: 'number', required: true },
{ name: 'Hauteur de levage (m)', type: 'number' },
{ name: 'Matériau des godets', type: 'string', defaultValue: 'Acier galvanisé' },
],
},
{
code: 'belt-conveyor',
name: 'Convoyeur à bande',
description:
'Convoyeur horizontal ou incliné assurant le transfert des grains entre les postes.',
customFields: [
{ name: 'Largeur de bande (mm)', type: 'number', required: true },
{ name: 'Longueur (m)', type: 'number' },
{ name: 'Type de bande', type: 'string', defaultValue: 'Caoutchouc anti-statique' },
],
},
{
code: 'gravity-separator',
name: 'Table densimétrique',
description:
'Séparateur gravimétrique permettant de retirer les impuretés lourdes ou légères.',
customFields: [
{ name: 'Capacité de tri (t/h)', type: 'number', required: true },
{ name: 'Fréquence de vibration (Hz)', type: 'number' },
{ name: 'Type de plateau', type: 'string', defaultValue: 'Acier perforé' },
],
},
{
code: 'grain-dryer',
name: 'Séchoir à grains',
description:
'Séchoir continu assurant la réduction du taux d\'humidité des céréales.',
customFields: [
{ name: 'Capacité sèche (t/h)', type: 'number', required: true },
{ name: "Nombre d'étages", type: 'number' },
{ name: "Type d'énergie", type: 'string', defaultValue: 'Gaz naturel' },
],
},
{
code: 'screw-conveyor',
name: 'Vis sans fin',
description: 'Vis de transfert pour la reprise des grains et le rechargement des silos.',
customFields: [
{ name: 'Diamètre vis (mm)', type: 'number', required: true },
{ name: 'Inclinaison (°)', type: 'number' },
{ name: 'Vitesse (rpm)', type: 'number' },
],
},
{
code: 'weigh-hopper',
name: 'Benna peseuse',
description: 'Benna équipée de capteurs de pesage pour le chargement précis des camions.',
customFields: [
{ name: 'Capacité de pesée (kg)', type: 'number', required: true },
{ name: 'Précision (%)', type: 'number' },
{ name: 'Nombre de capteurs', type: 'number', defaultValue: '4' },
],
},
{
code: 'control-panel',
name: 'Armoire de contrôle',
description: 'Armoire électrique pilotant l\'ensemble de la ligne de triage.',
customFields: [
{ name: 'Automate principal', type: 'string', required: true },
{ name: 'Année de mise à jour', type: 'number' },
{ name: "Indice de protection", type: 'string', defaultValue: 'IP55' },
],
},
{
code: 'telehandler',
name: 'Chariot télescopique',
description:
'Manitou utilisé pour les manutentions ponctuelles et la gestion des sacs big-bags.',
customFields: [
{ name: 'Capacité de levage (t)', type: 'number', required: true },
{ name: 'Hauteur de levage (m)', type: 'number' },
{ name: "Type d'attache", type: 'string', defaultValue: 'Fourches FEM' },
],
},
{
code: 'burner-module',
name: 'Module brûleur',
description: 'Module de combustion alimentant le séchoir en air chaud.',
customFields: [
{ name: 'Puissance thermique (kW)', type: 'number', required: true },
{ name: 'Type de carburant', type: 'string', defaultValue: 'Gaz naturel' },
{ name: "Système d'allumage", type: 'string', defaultValue: 'Double électrode' },
],
},
{
code: 'dust-filter',
name: 'Filtre à poussière',
description: 'Filtre à cyclone captant les poussières en sortie de séchoir.',
customFields: [
{ name: 'Efficacité de filtration (%)', type: 'number', required: true },
{ name: 'Type de média filtrant', type: 'string' },
{ name: 'Nombre de cartouches', type: 'number' },
],
},
];
const pieceTypeDefinitions: PieceTypeDefinition[] = [
{
code: 'electric-motor',
name: 'Moteur électrique',
description: 'Motorisation asynchrone IE3 pour entraînements industriels.',
customFields: [
{ name: 'Puissance nominale (kW)', type: 'number', required: true },
{ name: 'Tension (V)', type: 'number' },
{ name: "Indice de protection", type: 'string', defaultValue: 'IP55' },
],
},
{
code: 'speed-sensor',
name: 'Capteur de vitesse',
description: 'Capteur inductif contrôlant la vitesse des organes rotatifs.',
customFields: [
{ name: 'Type de sortie', type: 'string', required: true },
{ name: 'Plage de mesure (rpm)', type: 'number' },
],
},
{
code: 'temperature-probe',
name: 'Sonde de température',
description: 'Sonde PT100 pour la surveillance thermique du séchoir.',
customFields: [
{ name: 'Plage de mesure (°C)', type: 'string', required: true },
{ name: 'Type de sonde', type: 'string', defaultValue: 'PT100' },
],
},
{
code: 'belt',
name: 'Bande transporteuse',
description: 'Bande caoutchouc renforcée pour convoyeurs et élévateurs.',
customFields: [
{ name: 'Largeur (mm)', type: 'number', required: true },
{ name: 'Matériau', type: 'string' },
],
},
{
code: 'bearing',
name: 'Roulement',
description: 'Roulement à semelle pour transmissions tournantes.',
customFields: [
{ name: 'Référence fournisseur', type: 'string', required: true },
{ name: "Type d'étanchéité", type: 'string' },
],
},
{
code: 'gearbox',
name: 'Réducteur',
description: 'Réducteur de vitesse pour entraînement lourd.',
customFields: [
{ name: 'Rapport de réduction', type: 'string', required: true },
{ name: 'Couple nominal (Nm)', type: 'number' },
],
},
{
code: 'air-filter',
name: 'Filtre à air',
description: 'Cartouche filtrante pour dépoussiérage.',
customFields: [
{ name: 'Classe de filtration', type: 'string', required: true },
{ name: 'Dimensions (mm)', type: 'string' },
],
},
{
code: 'hydraulic-pump',
name: 'Pompe hydraulique',
description: 'Pompe hydraulique pour chariot télescopique.',
customFields: [
{ name: 'Débit nominal (l/min)', type: 'number', required: true },
{ name: 'Pression max (bar)', type: 'number' },
],
},
{
code: 'control-module',
name: 'Module automate',
description: 'Module PLC assurant le contrôle de ligne.',
customFields: [
{ name: "Nombre d'E/S", type: 'number', required: true },
{ name: 'Version firmware', type: 'string' },
],
},
{
code: 'load-cell',
name: 'Capteur de pesage',
description: 'Capteur de pesage pour benne peseuse.',
customFields: [
{ name: 'Capacité (kg)', type: 'number', required: true },
{ name: 'Sensibilité (mV/V)', type: 'string' },
],
},
];
const pieceModelDefinitions: PieceModelDefinition[] = [
{
code: 'motor-75kw',
name: 'Moteur IE3 75 kW',
description: 'Moteur principal pour élévateur haute capacité.',
typeCode: 'electric-motor',
structure: {
defaultCustomFieldValues: {
'Puissance nominale (kW)': '75',
'Tension (V)': '400',
"Indice de protection": 'IP55',
},
},
},
{
code: 'motor-45kw',
name: 'Moteur IE3 45 kW',
description: 'Motorisation pour convoyeur ou ventilateur.',
typeCode: 'electric-motor',
structure: {
defaultCustomFieldValues: {
'Puissance nominale (kW)': '45',
'Tension (V)': '400',
"Indice de protection": 'IP55',
},
},
},
{
code: 'motor-18kw',
name: 'Moteur IE3 18,5 kW',
description: 'Motorisation pour vis sans fin ou table densimétrique.',
typeCode: 'electric-motor',
structure: {
defaultCustomFieldValues: {
'Puissance nominale (kW)': '18.5',
'Tension (V)': '400',
"Indice de protection": 'IP55',
},
},
},
{
code: 'sensor-speed-m12',
name: 'Capteur inductif M12',
description: 'Capteur de vitesse inductif 4-20 mA.',
typeCode: 'speed-sensor',
structure: {
defaultCustomFieldValues: {
'Type de sortie': 'PNP 4-20 mA',
'Plage de mesure (rpm)': '0-1200',
},
},
},
{
code: 'temp-probe-pt100',
name: 'Sonde PT100 classe A',
description: 'Sonde PT100 pour mesure d\'air chaud.',
typeCode: 'temperature-probe',
structure: {
defaultCustomFieldValues: {
'Plage de mesure (°C)': '0-250',
'Type de sonde': 'PT100 classe A',
},
},
},
{
code: 'belt-hd-800',
name: 'Bande renforcée 800 mm',
description: 'Bande HD 800 mm anti-statique.',
typeCode: 'belt',
structure: {
defaultCustomFieldValues: {
'Largeur (mm)': '800',
'Matériau': 'Caoutchouc nitrile',
},
},
},
{
code: 'belt-hd-650',
name: 'Bande renforcée 650 mm',
description: 'Bande HD 650 mm résistante à l\'abrasion.',
typeCode: 'belt',
structure: {
defaultCustomFieldValues: {
'Largeur (mm)': '650',
'Matériau': 'Caoutchouc anti-abrasion',
},
},
},
{
code: 'bearing-ucp210',
name: 'Roulement UCP210',
description: 'Roulement à semelle graissable.',
typeCode: 'bearing',
structure: {
defaultCustomFieldValues: {
'Référence fournisseur': 'SKF UCP210',
"Type d'étanchéité": '2RS',
},
},
},
{
code: 'gearbox-flender',
name: 'Réducteur Flender FZ',
description: 'Réducteur coaxial pour charge lourde.',
typeCode: 'gearbox',
structure: {
defaultCustomFieldValues: {
'Rapport de réduction': '1:28',
'Couple nominal (Nm)': '3200',
},
},
},
{
code: 'filter-g4-500',
name: 'Filtre G4 500x500',
description: 'Cartouche filtrante G4 pour dépoussiérage.',
typeCode: 'air-filter',
structure: {
defaultCustomFieldValues: {
'Classe de filtration': 'G4',
'Dimensions (mm)': '500x500x50',
},
},
},
{
code: 'hydraulic-pump-pvh98',
name: 'Pompe hydraulique PVH98',
description: 'Pompe haute pression pour Manitou.',
typeCode: 'hydraulic-pump',
structure: {
defaultCustomFieldValues: {
'Débit nominal (l/min)': '160',
'Pression max (bar)': '320',
},
},
},
{
code: 'plc-module-siemens-1512',
name: 'Module PLC Siemens 1512',
description: 'Automate Siemens S7-1500 1512SP.',
typeCode: 'control-module',
structure: {
defaultCustomFieldValues: {
"Nombre d'E/S": '32',
'Version firmware': 'V2.9',
},
},
},
{
code: 'load-cell-5t',
name: 'Capteur de pesage 5 t',
description: 'Capteur de pesage IP68 pour benne peseuse.',
typeCode: 'load-cell',
structure: {
defaultCustomFieldValues: {
'Capacité (kg)': '5000',
'Sensibilité (mV/V)': '2.0',
},
},
},
];
const componentModelDefinitions: ComponentModelDefinition[] = [
{
code: 'elevator-z400',
name: 'Élévateur Z400',
description: 'Élévateur à godets 120 t/h, 38 m.',
typeCode: 'bucket-elevator',
structure: {
defaultPieces: [
{ modelCode: 'motor-75kw', role: 'Motorisation principale' },
{ modelCode: 'gearbox-flender', role: 'Réducteur' },
{ modelCode: 'belt-hd-800', role: 'Courroie élévateur' },
{ modelCode: 'sensor-speed-m12', role: 'Capteur vitesse tête' },
{ modelCode: 'bearing-ucp210', role: 'Paliers de tête' },
],
recommendedCustomFields: {
'Débit nominal (t/h)': '120',
'Hauteur de levage (m)': '38',
'Matériau des godets': 'Acier galvanisé',
},
},
},
{
code: 'conveyor-18m',
name: 'Convoyeur bande 18 m',
description: 'Convoyeur à bande 800 mm, 18 mètres.',
typeCode: 'belt-conveyor',
structure: {
defaultPieces: [
{ modelCode: 'motor-45kw', role: 'Motorisation' },
{ modelCode: 'belt-hd-800', role: 'Bande transporteuse' },
{ modelCode: 'sensor-speed-m12', role: 'Capteur rotation' },
],
recommendedCustomFields: {
'Largeur de bande (mm)': '800',
'Longueur (m)': '18',
'Type de bande': 'Caoutchouc anti-statique',
},
},
},
{
code: 'gravity-table-tqx',
name: 'Table densimétrique TQX-120',
description: 'Table densimétrique haute précision 120 t/h.',
typeCode: 'gravity-separator',
structure: {
defaultPieces: [
{ modelCode: 'motor-18kw', role: 'Motorisation vibration' },
{ modelCode: 'sensor-speed-m12', role: 'Capteur vibration' },
],
recommendedCustomFields: {
'Capacité de tri (t/h)': '120',
'Fréquence de vibration (Hz)': '45',
'Type de plateau': 'Acier perforé',
},
},
},
{
code: 'grain-dryer-cd6',
name: 'Séchoir continu CD-6',
description: 'Séchoir continu 6 étages avec récupération de chaleur.',
typeCode: 'grain-dryer',
structure: {
defaultPieces: [
{ modelCode: 'motor-45kw', role: 'Ventilateur principal' },
{ modelCode: 'temp-probe-pt100', role: 'Sonde air chaud' },
],
subComponents: [
{ modelCode: 'burner-module-3mw', role: 'Brûleur gaz principal' },
{ modelCode: 'dust-filter-fc12', role: 'Filtre cyclone' },
],
recommendedCustomFields: {
'Capacité sèche (t/h)': '60',
"Nombre d'étages": '6',
"Type d'énergie": 'Gaz naturel',
},
},
},
{
code: 'screw-conveyor-v200',
name: 'Vis sans fin V200',
description: 'Vis de reprise diamètre 200 mm.',
typeCode: 'screw-conveyor',
structure: {
defaultPieces: [
{ modelCode: 'motor-18kw', role: 'Motorisation vis' },
{ modelCode: 'bearing-ucp210', role: 'Paliers supports' },
],
recommendedCustomFields: {
'Diamètre vis (mm)': '200',
'Inclinaison (°)': '12',
'Vitesse (rpm)': '140',
},
},
},
{
code: 'weigh-hopper-bp5',
name: 'Benna peseuse BP-5',
description: 'Benna peseuse 5 tonnes pour chargement camion.',
typeCode: 'weigh-hopper',
structure: {
defaultPieces: [
{ modelCode: 'load-cell-5t', role: 'Capteurs de pesage' },
{ modelCode: 'sensor-speed-m12', role: 'Capteur rotation trappe' },
],
recommendedCustomFields: {
'Capacité de pesée (kg)': '5000',
'Précision (%)': '0.5',
'Nombre de capteurs': '4',
},
},
},
{
code: 'control-panel-m340',
name: 'Armoire Schneider M340',
description: 'Armoire Schneider Electric avec automate M340.',
typeCode: 'control-panel',
structure: {
defaultPieces: [
{ modelCode: 'plc-module-siemens-1512', role: 'Automate principal' },
{ modelCode: 'sensor-speed-m12', role: 'Entrée vitesse générale' },
],
recommendedCustomFields: {
'Automate principal': 'Schneider Modicon M340',
'Année de mise à jour': '2023',
"Indice de protection": 'IP55',
},
},
},
{
code: 'burner-module-3mw',
name: 'Brûleur gaz 3 MW',
description: 'Brûleur gaz modulant 3 MW pour séchoir.',
typeCode: 'burner-module',
structure: {
defaultPieces: [
{ modelCode: 'temp-probe-pt100', role: 'Sonde sécurité flamme' },
],
recommendedCustomFields: {
'Puissance thermique (kW)': '3000',
'Type de carburant': 'Gaz naturel',
"Système d'allumage": 'Double électrode',
},
},
},
{
code: 'dust-filter-fc12',
name: 'Filtre cyclone FC-12',
description: 'Filtre cyclone avec cartouches G4.',
typeCode: 'dust-filter',
structure: {
defaultPieces: [
{ modelCode: 'filter-g4-500', role: 'Cartouche filtrante' },
],
recommendedCustomFields: {
'Efficacité de filtration (%)': '95',
'Type de média filtrant': 'Polyester',
'Nombre de cartouches': '6',
},
},
},
{
code: 'telehandler-mlt1040',
name: 'Manitou MLT 1040',
description: 'Chariot télescopique Manitou 4 t.',
typeCode: 'telehandler',
structure: {
defaultPieces: [
{ modelCode: 'hydraulic-pump-pvh98', role: 'Pompe hydraulique principale' },
{ modelCode: 'bearing-ucp210', role: 'Articulation de flèche' },
],
recommendedCustomFields: {
'Capacité de levage (t)': '4',
'Hauteur de levage (m)': '9.6',
"Type d'attache": 'Fourches FEM',
},
},
},
];
const constructeurDefinitions: ConstructeurDefinition[] = [
{
key: 'agritech',
name: 'AgriTech Elevators',
email: 'support@agritech-elevators.fr',
phone: '+33 3 74 01 20 10',
},
{
key: 'valmont',
name: 'Valmont Conveyors',
email: 'info@valmont-conveyors.com',
phone: '+33 3 80 45 77 20',
},
{
key: 'buhler',
name: 'Bühler Sortex',
email: 'service@buhlergroup.com',
phone: '+41 71 955 11 11',
},
{
key: 'agridry',
name: 'AgriDry Solutions',
email: 'contact@agridry.eu',
phone: '+33 4 74 22 55 90',
},
{
key: 'sew',
name: 'SEW-Eurodrive',
email: 'contact@sew-eurodrive.fr',
phone: '+33 3 88 73 67 00',
},
{
key: 'skf',
name: 'SKF France',
email: 'support@skf.com',
phone: '+33 1 30 57 67 00',
},
{
key: 'schneider',
name: 'Schneider Electric',
email: 'contact@se.com',
phone: '+33 1 47 29 70 00',
},
{
key: 'manitou',
name: 'Manitou BF',
email: 'support@manitou-group.com',
phone: '+33 2 40 09 10 11',
},
{
key: 'flender',
name: 'Flender GmbH',
email: 'service@flender.com',
phone: '+49 521 525 0',
},
{
key: 'ifm',
name: 'ifm electronic',
email: 'info.fr@ifm.com',
phone: '+33 1 45 12 24 00',
},
{
key: 'siemens',
name: 'Siemens Industry',
email: 'industry.fr@siemens.com',
phone: '+33 1 85 57 00 00',
},
];
async function clearDatabaseExceptSitesAndProfiles() {
console.log('🧹 Nettoyage des tables (hors sites et profils)...');
const deleteOrder = [
prisma.customFieldValue.deleteMany(),
prisma.document.deleteMany(),
prisma.piece.deleteMany(),
prisma.composant.deleteMany(),
prisma.machine.deleteMany(),
prisma.typeMachineComponentRequirement.deleteMany(),
prisma.typeMachinePieceRequirement.deleteMany(),
prisma.customField.deleteMany(),
prisma.pieceModel.deleteMany(),
prisma.composantModel.deleteMany(),
prisma.typeMachine.deleteMany(),
prisma.modelType.deleteMany(),
prisma.constructeur.deleteMany(),
];
for (const promise of deleteOrder) {
await promise;
}
console.log('✅ Tables nettoyées.');
}
async function ensureDemoSite() {
const existingSite = await prisma.site.findFirst();
if (existingSite) {
return existingSite;
}
console.log('🏗️ Création du site de démonstration...');
return prisma.site.create({
data: {
name: 'Usine de triage Valgrain',
contactName: 'Lucie Bernard',
contactPhone: '+33 3 80 12 45 78',
contactAddress: 'Zone industrielle des Platanes',
contactPostalCode: '21000',
contactCity: 'Dijon',
},
});
}
async function createConstructeurs() {
console.log('🏭 Création des constructeurs...');
const entries = await Promise.all(
constructeurDefinitions.map((definition) =>
prisma.constructeur
.create({
data: {
name: definition.name,
email: definition.email,
phone: definition.phone,
},
})
.then((constructeur) => [definition.key, constructeur] as const),
),
);
return Object.fromEntries(entries) as Record<string, { id: string }>;
}
function mapCustomFields(
fields: { id: string; name: string }[],
): Record<string, string> {
return fields.reduce<Record<string, string>>((acc, field) => {
acc[field.name] = field.id;
return acc;
}, {});
}
async function createModelTypes() {
console.log('🗂️ Création des catégories de composants et pièces...');
const componentTypeEntries: [
string,
{
id: string;
customFields: Record<string, string>;
},
][] = [];
for (const definition of componentTypeDefinitions) {
const record = await prisma.modelType.create({
data: {
name: definition.name,
code: definition.code,
category: ModelCategory.COMPONENT,
description: definition.description,
customFields: {
create: definition.customFields.map((field) => ({
name: field.name,
type: field.type,
required: field.required ?? false,
defaultValue: field.defaultValue,
options: field.options ?? [],
})),
},
},
include: {
customFields: true,
},
});
componentTypeEntries.push([
definition.code,
{
id: record.id,
customFields: mapCustomFields(record.customFields),
},
]);
}
const pieceTypeEntries: [
string,
{
id: string;
customFields: Record<string, string>;
},
][] = [];
for (const definition of pieceTypeDefinitions) {
const record = await prisma.modelType.create({
data: {
name: definition.name,
code: definition.code,
category: ModelCategory.PIECE,
description: definition.description,
pieceCustomFields: {
create: definition.customFields.map((field) => ({
name: field.name,
type: field.type,
required: field.required ?? false,
defaultValue: field.defaultValue,
options: field.options ?? [],
})),
},
},
include: {
pieceCustomFields: true,
},
});
pieceTypeEntries.push([
definition.code,
{
id: record.id,
customFields: mapCustomFields(record.pieceCustomFields),
},
]);
}
return {
componentTypes: Object.fromEntries(componentTypeEntries) as Record<
string,
{ id: string; customFields: Record<string, string> }
>,
pieceTypes: Object.fromEntries(pieceTypeEntries) as Record<
string,
{ id: string; customFields: Record<string, string> }
>,
};
}
async function createPieceModels(pieceTypes: Record<string, { id: string }>) {
console.log('🔧 Création des modèles de pièces...');
const entries = await Promise.all(
pieceModelDefinitions.map(async (definition) => {
const record = await prisma.pieceModel.create({
data: {
name: definition.name,
description: definition.description,
typePiece: { connect: { id: pieceTypes[definition.typeCode].id } },
structure: definition.structure ?? Prisma.JsonNull,
},
});
return [definition.code, record] as const;
}),
);
return Object.fromEntries(entries) as Record<string, { id: string }>;
}
async function createComponentModels(
componentTypes: Record<string, { id: string }>,
) {
console.log('🧱 Création des modèles de composants...');
const entries = await Promise.all(
componentModelDefinitions.map(async (definition) => {
const record = await prisma.composantModel.create({
data: {
name: definition.name,
description: definition.description,
typeComposant: { connect: { id: componentTypes[definition.typeCode].id } },
structure: definition.structure ?? Prisma.JsonNull,
},
});
return [definition.code, record] as const;
}),
);
return Object.fromEntries(entries) as Record<string, { id: string }>;
}
async function createTypeMachine(
componentTypes: Record<string, { id: string }>,
pieceTypes: Record<string, { id: string }>,
) {
console.log('🧬 Création du squelette de machine...');
const typeMachine = await prisma.typeMachine.create({
data: {
name: 'Ligne de triage et séchage céréales 120 t/h',
description:
'Chaîne automatisée de réception, triage, séchage et expédition des céréales.',
category: 'Triage et stockage',
maintenanceFrequency:
'Inspection quotidienne, graissage hebdomadaire, révision trimestrielle.',
specifications: {
nominalThroughput: 120,
moistureTarget: 14.5,
building: 'Hall principal',
shiftsPerDay: 2,
},
components: {
layout: [
{ order: 1, zone: 'Réception', type: 'bucket-elevator', model: 'elevator-z400' },
{ order: 2, zone: 'Pré-nettoyage', type: 'belt-conveyor', model: 'conveyor-18m' },
{ order: 3, zone: 'Séparation', type: 'gravity-separator', model: 'gravity-table-tqx' },
{ order: 4, zone: 'Séchage', type: 'grain-dryer', model: 'grain-dryer-cd6' },
{ order: 5, zone: 'Reprise', type: 'screw-conveyor', model: 'screw-conveyor-v200' },
{ order: 6, zone: 'Expédition', type: 'weigh-hopper', model: 'weigh-hopper-bp5' },
],
},
criticalParts: {
motors: ['motor-75kw', 'motor-45kw'],
sensors: ['sensor-speed-m12', 'temp-probe-pt100'],
wearItems: ['belt-hd-800', 'filter-g4-500'],
},
machinePieces: {
recommendedStock: [
{ model: 'motor-75kw', quantity: 1 },
{ model: 'sensor-speed-m12', quantity: 3 },
{ model: 'belt-hd-800', quantity: 1 },
],
},
customFields: {
create: [
{
name: 'Capacité nominale (t/h)',
type: 'number',
required: true,
options: [],
},
{
name: 'Produit traité',
type: 'string',
required: true,
defaultValue: 'Blé tendre',
options: [],
},
{
name: 'Date de mise en service',
type: 'date',
required: true,
options: [],
},
{
name: 'Responsable de ligne',
type: 'string',
required: false,
defaultValue: 'Lucie Bernard',
options: [],
},
],
},
componentRequirements: {
create: [
{
label: 'Élévateurs principaux',
minCount: 2,
maxCount: 2,
required: true,
typeComposant: { connect: { id: componentTypes['bucket-elevator'].id } },
},
{
label: "Convoyeurs d'alimentation",
minCount: 2,
required: true,
typeComposant: { connect: { id: componentTypes['belt-conveyor'].id } },
},
{
label: 'Table densimétrique',
minCount: 1,
maxCount: 1,
required: true,
typeComposant: { connect: { id: componentTypes['gravity-separator'].id } },
},
{
label: 'Séchoir continu',
minCount: 1,
maxCount: 1,
required: true,
typeComposant: { connect: { id: componentTypes['grain-dryer'].id } },
},
{
label: 'Vis de reprise',
minCount: 2,
required: true,
typeComposant: { connect: { id: componentTypes['screw-conveyor'].id } },
},
{
label: 'Benna peseuse',
minCount: 1,
required: true,
typeComposant: { connect: { id: componentTypes['weigh-hopper'].id } },
},
{
label: 'Armoire de contrôle',
minCount: 1,
maxCount: 1,
required: true,
typeComposant: { connect: { id: componentTypes['control-panel'].id } },
},
{
label: 'Chariot télescopique',
minCount: 1,
required: false,
typeComposant: { connect: { id: componentTypes['telehandler'].id } },
},
],
},
pieceRequirements: {
create: [
{
label: 'Moteurs de rechange',
minCount: 1,
required: false,
typePiece: { connect: { id: pieceTypes['electric-motor'].id } },
},
{
label: 'Capteurs de vitesse de secours',
minCount: 2,
required: false,
typePiece: { connect: { id: pieceTypes['speed-sensor'].id } },
},
],
},
},
include: {
customFields: true,
componentRequirements: true,
pieceRequirements: true,
},
});
return typeMachine;
}
function buildCustomFieldValues(
fieldMap: Record<string, string>,
values?: Record<string, string | number | boolean | Date>,
) {
if (!values) {
return undefined;
}
return {
create: Object.entries(values).map(([name, value]) => {
const fieldId = fieldMap[name];
if (!fieldId) {
throw new Error(`Champ personnalisé inconnu: ${name}`);
}
return {
value: value instanceof Date ? value.toISOString() : String(value),
customField: {
connect: { id: fieldId },
},
};
}),
};
}
async function createComponentHierarchy(
machineId: string,
component: ComponentInstance,
context: {
componentTypes: Record<string, { id: string; customFields: Record<string, string> }>;
componentModels: Record<string, { id: string }>;
pieceTypes: Record<string, { id: string; customFields: Record<string, string> }>;
pieceModels: Record<string, { id: string }>;
constructeurs: Record<string, { id: string }>;
requirementMap: Map<string, string>;
},
parentId?: string,
) {
const requirementId = component.requirementLabel
? context.requirementMap.get(component.requirementLabel)
: undefined;
const record = await prisma.composant.create({
data: {
name: component.name,
reference: component.reference,
prix: component.prix ? new Prisma.Decimal(component.prix) : undefined,
machine: { connect: { id: machineId } },
parentComposant: parentId ? { connect: { id: parentId } } : undefined,
typeComposant: {
connect: { id: context.componentTypes[component.typeCode].id },
},
composantModel: {
connect: { id: context.componentModels[component.modelCode].id },
},
typeMachineComponentRequirement: requirementId
? { connect: { id: requirementId } }
: undefined,
constructeur: component.constructeur
? { connect: { id: context.constructeurs[component.constructeur].id } }
: undefined,
customFieldValues: buildCustomFieldValues(
context.componentTypes[component.typeCode].customFields,
component.customValues,
),
pieces: component.pieces
? {
create: component.pieces.map((piece) => {
const type = context.pieceTypes[piece.typeCode];
if (!type) {
throw new Error(`Type de pièce introuvable: ${piece.typeCode}`);
}
return {
name: piece.name,
reference: piece.reference,
prix: piece.prix ? new Prisma.Decimal(piece.prix) : undefined,
typePiece: { connect: { id: type.id } },
pieceModel: {
connect: { id: context.pieceModels[piece.modelCode].id },
},
constructeur: piece.constructeur
? { connect: { id: context.constructeurs[piece.constructeur].id } }
: undefined,
customFieldValues: buildCustomFieldValues(
type.customFields,
piece.customValues,
),
};
}),
}
: undefined,
},
});
if (component.children && component.children.length > 0) {
for (const child of component.children) {
await createComponentHierarchy(machineId, child, context, record.id);
}
}
return record;
}
async function createMachineWithComponents(
siteId: string,
typeMachine: Awaited<ReturnType<typeof createTypeMachine>>,
context: {
componentTypes: Record<string, { id: string; customFields: Record<string, string> }>;
componentModels: Record<string, { id: string }>;
pieceTypes: Record<string, { id: string; customFields: Record<string, string> }>;
pieceModels: Record<string, { id: string }>;
constructeurs: Record<string, { id: string }>;
},
) {
console.log('🏗️ Création de la machine de démonstration...');
const requirementMap = new Map<string, string>();
typeMachine.componentRequirements.forEach((requirement) => {
if (requirement.label) {
requirementMap.set(requirement.label, requirement.id);
}
});
const pieceRequirementMap = new Map<string, string>();
typeMachine.pieceRequirements.forEach((requirement) => {
if (requirement.label) {
pieceRequirementMap.set(requirement.label, requirement.id);
}
});
const machineCustomFieldMap = mapCustomFields(typeMachine.customFields);
const machine = await prisma.machine.create({
data: {
name: 'Ligne de triage Valgrain 2024',
reference: 'VT-TRI-2024',
prix: new Prisma.Decimal('725000'),
site: { connect: { id: siteId } },
typeMachine: { connect: { id: typeMachine.id } },
constructeur: { connect: { id: context.constructeurs['buhler'].id } },
customFieldValues: buildCustomFieldValues(machineCustomFieldMap, {
'Capacité nominale (t/h)': 120,
'Produit traité': 'Blé tendre, orge brassicole',
'Date de mise en service': new Date('2024-02-01'),
'Responsable de ligne': 'Lucie Bernard',
}),
},
});
console.log('⚙️ Ajout des composants et sous-ensembles...');
const componentContext = {
...context,
requirementMap,
};
const components: ComponentInstance[] = [
{
name: 'Élévateur amont Z400',
reference: 'BE-Z400-01',
prix: '58000',
typeCode: 'bucket-elevator',
requirementLabel: 'Élévateurs principaux',
modelCode: 'elevator-z400',
constructeur: 'agritech',
customValues: {
'Débit nominal (t/h)': 120,
'Hauteur de levage (m)': 38,
'Matériau des godets': 'Acier galvanisé',
},
pieces: [
{
name: 'Moteur principal 75 kW',
reference: 'MTR-75-01',
prix: '8200',
typeCode: 'electric-motor',
modelCode: 'motor-75kw',
constructeur: 'sew',
customValues: {
'Puissance nominale (kW)': 75,
'Tension (V)': 400,
"Indice de protection": 'IP55',
},
},
{
name: 'Réducteur Flender FZ',
reference: 'GBX-FZ-01',
prix: '5100',
typeCode: 'gearbox',
modelCode: 'gearbox-flender',
constructeur: 'flender',
customValues: {
'Rapport de réduction': '1:28',
'Couple nominal (Nm)': 3200,
},
},
{
name: 'Courroie élévateur 800 mm',
reference: 'BLT-800-01',
prix: '2300',
typeCode: 'belt',
modelCode: 'belt-hd-800',
constructeur: 'agritech',
customValues: {
'Largeur (mm)': 800,
'Matériau': 'Caoutchouc nitrile',
},
},
{
name: 'Capteur vitesse tête',
reference: 'SNS-VIT-01',
typeCode: 'speed-sensor',
modelCode: 'sensor-speed-m12',
constructeur: 'ifm',
customValues: {
'Type de sortie': 'PNP 4-20 mA',
'Plage de mesure (rpm)': 1200,
},
},
{
name: 'Roulement tête élévateur',
reference: 'BRG-UCP210-01',
typeCode: 'bearing',
modelCode: 'bearing-ucp210',
constructeur: 'skf',
customValues: {
'Référence fournisseur': 'SKF UCP210',
"Type d'étanchéité": '2RS',
},
},
],
},
{
name: 'Élévateur aval Z400',
reference: 'BE-Z400-02',
prix: '56800',
typeCode: 'bucket-elevator',
requirementLabel: 'Élévateurs principaux',
modelCode: 'elevator-z400',
constructeur: 'agritech',
customValues: {
'Débit nominal (t/h)': 115,
'Hauteur de levage (m)': 36,
'Matériau des godets': 'Acier galvanisé',
},
pieces: [
{
name: 'Moteur principal 75 kW (aval)',
reference: 'MTR-75-02',
prix: '8150',
typeCode: 'electric-motor',
modelCode: 'motor-75kw',
constructeur: 'sew',
customValues: {
'Puissance nominale (kW)': 75,
'Tension (V)': 400,
"Indice de protection": 'IP55',
},
},
{
name: 'Courroie élévateur 800 mm (aval)',
reference: 'BLT-800-02',
typeCode: 'belt',
modelCode: 'belt-hd-800',
constructeur: 'agritech',
customValues: {
'Largeur (mm)': 800,
'Matériau': 'Caoutchouc nitrile',
},
},
{
name: 'Capteur vitesse aval',
reference: 'SNS-VIT-02',
typeCode: 'speed-sensor',
modelCode: 'sensor-speed-m12',
constructeur: 'ifm',
customValues: {
'Type de sortie': 'PNP 4-20 mA',
'Plage de mesure (rpm)': 1100,
},
},
],
},
{
name: "Convoyeur alimentation réception",
reference: 'CV-ALIM-01',
prix: '24500',
typeCode: 'belt-conveyor',
requirementLabel: "Convoyeurs d'alimentation",
modelCode: 'conveyor-18m',
constructeur: 'valmont',
customValues: {
'Largeur de bande (mm)': 800,
'Longueur (m)': 18,
'Type de bande': 'Caoutchouc anti-statique',
},
pieces: [
{
name: 'Moteur convoyeur 45 kW',
reference: 'MTR-45-01',
prix: '6100',
typeCode: 'electric-motor',
modelCode: 'motor-45kw',
constructeur: 'sew',
customValues: {
'Puissance nominale (kW)': 45,
'Tension (V)': 400,
"Indice de protection": 'IP55',
},
},
{
name: 'Bande transporteuse 800 mm',
reference: 'BLT-800-03',
typeCode: 'belt',
modelCode: 'belt-hd-800',
constructeur: 'valmont',
customValues: {
'Largeur (mm)': 800,
'Matériau': 'Caoutchouc anti-abrasion',
},
},
{
name: 'Capteur vitesse convoyeur',
reference: 'SNS-VIT-03',
typeCode: 'speed-sensor',
modelCode: 'sensor-speed-m12',
constructeur: 'ifm',
customValues: {
'Type de sortie': 'PNP 4-20 mA',
'Plage de mesure (rpm)': 900,
},
},
],
},
{
name: "Convoyeur alimentation séparateur",
reference: 'CV-ALIM-02',
prix: '23200',
typeCode: 'belt-conveyor',
requirementLabel: "Convoyeurs d'alimentation",
modelCode: 'conveyor-18m',
constructeur: 'valmont',
customValues: {
'Largeur de bande (mm)': 650,
'Longueur (m)': 15,
'Type de bande': 'Caoutchouc anti-statique',
},
pieces: [
{
name: 'Moteur convoyeur 45 kW (séparateur)',
reference: 'MTR-45-02',
typeCode: 'electric-motor',
modelCode: 'motor-45kw',
constructeur: 'sew',
customValues: {
'Puissance nominale (kW)': 45,
'Tension (V)': 400,
"Indice de protection": 'IP55',
},
},
{
name: 'Bande transporteuse 650 mm',
reference: 'BLT-650-01',
typeCode: 'belt',
modelCode: 'belt-hd-650',
constructeur: 'valmont',
customValues: {
'Largeur (mm)': 650,
'Matériau': 'Caoutchouc anti-abrasion',
},
},
{
name: 'Capteur vitesse convoyeur 2',
reference: 'SNS-VIT-04',
typeCode: 'speed-sensor',
modelCode: 'sensor-speed-m12',
constructeur: 'ifm',
customValues: {
'Type de sortie': 'PNP 4-20 mA',
'Plage de mesure (rpm)': 850,
},
},
],
},
{
name: 'Table densimétrique TQX-120',
reference: 'TBL-TQX-01',
prix: '68500',
typeCode: 'gravity-separator',
requirementLabel: 'Table densimétrique',
modelCode: 'gravity-table-tqx',
constructeur: 'buhler',
customValues: {
'Capacité de tri (t/h)': 120,
'Fréquence de vibration (Hz)': 45,
'Type de plateau': 'Acier perforé',
},
pieces: [
{
name: 'Moteur vibration 18,5 kW',
reference: 'MTR-18-01',
typeCode: 'electric-motor',
modelCode: 'motor-18kw',
constructeur: 'sew',
customValues: {
'Puissance nominale (kW)': 18.5,
'Tension (V)': 400,
"Indice de protection": 'IP55',
},
},
{
name: 'Capteur vibration table',
reference: 'SNS-VIB-01',
typeCode: 'speed-sensor',
modelCode: 'sensor-speed-m12',
constructeur: 'ifm',
customValues: {
'Type de sortie': 'PNP 4-20 mA',
'Plage de mesure (rpm)': 600,
},
},
],
},
{
name: 'Séchoir continu CD-6',
reference: 'DRY-CD6-01',
prix: '148000',
typeCode: 'grain-dryer',
requirementLabel: 'Séchoir continu',
modelCode: 'grain-dryer-cd6',
constructeur: 'agridry',
customValues: {
'Capacité sèche (t/h)': 60,
"Nombre d'étages": 6,
"Type d'énergie": 'Gaz naturel',
},
pieces: [
{
name: 'Ventilateur principal 45 kW',
reference: 'MTR-45-03',
typeCode: 'electric-motor',
modelCode: 'motor-45kw',
constructeur: 'sew',
customValues: {
'Puissance nominale (kW)': 45,
'Tension (V)': 400,
"Indice de protection": 'IP55',
},
},
{
name: "Sonde air chaud PT100",
reference: 'TMP-PT100-01',
typeCode: 'temperature-probe',
modelCode: 'temp-probe-pt100',
constructeur: 'ifm',
customValues: {
'Plage de mesure (°C)': '0-250',
'Type de sonde': 'PT100 classe A',
},
},
],
children: [
{
name: 'Brûleur gaz modulant',
reference: 'BRN-3MW-01',
typeCode: 'burner-module',
modelCode: 'burner-module-3mw',
constructeur: 'agridry',
customValues: {
'Puissance thermique (kW)': 2950,
'Type de carburant': 'Gaz naturel',
"Système d'allumage": 'Double électrode',
},
pieces: [
{
name: 'Sonde sécurité flamme',
reference: 'TMP-PT100-02',
typeCode: 'temperature-probe',
modelCode: 'temp-probe-pt100',
constructeur: 'ifm',
customValues: {
'Plage de mesure (°C)': '0-250',
'Type de sonde': 'PT100 classe A',
},
},
],
},
{
name: 'Filtre cyclone FC-12',
reference: 'FLT-FC12-01',
typeCode: 'dust-filter',
modelCode: 'dust-filter-fc12',
constructeur: 'agridry',
customValues: {
'Efficacité de filtration (%)': 95,
'Type de média filtrant': 'Polyester',
'Nombre de cartouches': 6,
},
pieces: [
{
name: 'Cartouche filtrante G4',
reference: 'FLT-G4-01',
typeCode: 'air-filter',
modelCode: 'filter-g4-500',
constructeur: 'agridry',
customValues: {
'Classe de filtration': 'G4',
'Dimensions (mm)': '500x500x50',
},
},
],
},
],
},
{
name: 'Vis de reprise nord',
reference: 'SC-V200-01',
prix: '18400',
typeCode: 'screw-conveyor',
requirementLabel: 'Vis de reprise',
modelCode: 'screw-conveyor-v200',
constructeur: 'valmont',
customValues: {
'Diamètre vis (mm)': 200,
'Inclinaison (°)': 10,
'Vitesse (rpm)': 140,
},
pieces: [
{
name: 'Moteur vis 18,5 kW',
reference: 'MTR-18-02',
typeCode: 'electric-motor',
modelCode: 'motor-18kw',
constructeur: 'sew',
customValues: {
'Puissance nominale (kW)': 18.5,
'Tension (V)': 400,
"Indice de protection": 'IP55',
},
},
{
name: 'Palier vis nord',
reference: 'BRG-UCP210-02',
typeCode: 'bearing',
modelCode: 'bearing-ucp210',
constructeur: 'skf',
customValues: {
'Référence fournisseur': 'SKF UCP210',
"Type d'étanchéité": '2RS',
},
},
],
},
{
name: 'Vis de reprise sud',
reference: 'SC-V200-02',
prix: '18100',
typeCode: 'screw-conveyor',
requirementLabel: 'Vis de reprise',
modelCode: 'screw-conveyor-v200',
constructeur: 'valmont',
customValues: {
'Diamètre vis (mm)': 200,
'Inclinaison (°)': 12,
'Vitesse (rpm)': 145,
},
pieces: [
{
name: 'Moteur vis 18,5 kW (sud)',
reference: 'MTR-18-03',
typeCode: 'electric-motor',
modelCode: 'motor-18kw',
constructeur: 'sew',
customValues: {
'Puissance nominale (kW)': 18.5,
'Tension (V)': 400,
"Indice de protection": 'IP55',
},
},
{
name: 'Palier vis sud',
reference: 'BRG-UCP210-03',
typeCode: 'bearing',
modelCode: 'bearing-ucp210',
constructeur: 'skf',
customValues: {
'Référence fournisseur': 'SKF UCP210',
"Type d'étanchéité": '2RS',
},
},
],
},
{
name: 'Benna peseuse BP-5',
reference: 'BP-5000-01',
prix: '39200',
typeCode: 'weigh-hopper',
requirementLabel: 'Benna peseuse',
modelCode: 'weigh-hopper-bp5',
constructeur: 'buhler',
customValues: {
'Capacité de pesée (kg)': 5000,
'Précision (%)': 0.5,
'Nombre de capteurs': 4,
},
pieces: [
{
name: 'Capteur pesage 1',
reference: 'LC-5000-01',
typeCode: 'load-cell',
modelCode: 'load-cell-5t',
constructeur: 'ifm',
customValues: {
'Capacité (kg)': 5000,
'Sensibilité (mV/V)': '2.0',
},
},
{
name: 'Capteur pesage 2',
reference: 'LC-5000-02',
typeCode: 'load-cell',
modelCode: 'load-cell-5t',
constructeur: 'ifm',
customValues: {
'Capacité (kg)': 5000,
'Sensibilité (mV/V)': '2.0',
},
},
{
name: 'Capteur pesage 3',
reference: 'LC-5000-03',
typeCode: 'load-cell',
modelCode: 'load-cell-5t',
constructeur: 'ifm',
customValues: {
'Capacité (kg)': 5000,
'Sensibilité (mV/V)': '2.0',
},
},
{
name: 'Capteur pesage 4',
reference: 'LC-5000-04',
typeCode: 'load-cell',
modelCode: 'load-cell-5t',
constructeur: 'ifm',
customValues: {
'Capacité (kg)': 5000,
'Sensibilité (mV/V)': '2.0',
},
},
],
},
{
name: 'Armoire Schneider M340',
reference: 'CTRL-M340-01',
prix: '46500',
typeCode: 'control-panel',
requirementLabel: 'Armoire de contrôle',
modelCode: 'control-panel-m340',
constructeur: 'schneider',
customValues: {
'Automate principal': 'Schneider Modicon M340',
'Année de mise à jour': 2023,
"Indice de protection": 'IP55',
},
pieces: [
{
name: 'Module PLC Siemens 1512',
reference: 'PLC-1512-01',
typeCode: 'control-module',
modelCode: 'plc-module-siemens-1512',
constructeur: 'siemens',
customValues: {
"Nombre d'E/S": 32,
'Version firmware': 'V2.9',
},
},
{
name: 'Entrée vitesse ligne',
reference: 'SNS-VIT-CTRL-01',
typeCode: 'speed-sensor',
modelCode: 'sensor-speed-m12',
constructeur: 'ifm',
customValues: {
'Type de sortie': 'PNP 4-20 mA',
'Plage de mesure (rpm)': 1000,
},
},
],
},
{
name: 'Chariot télescopique Manitou',
reference: 'MLT-1040-01',
prix: '73500',
typeCode: 'telehandler',
requirementLabel: 'Chariot télescopique',
modelCode: 'telehandler-mlt1040',
constructeur: 'manitou',
customValues: {
'Capacité de levage (t)': 4,
'Hauteur de levage (m)': 9.6,
"Type d'attache": 'Fourches FEM',
},
pieces: [
{
name: 'Pompe hydraulique principale',
reference: 'HDP-PVH98-01',
typeCode: 'hydraulic-pump',
modelCode: 'hydraulic-pump-pvh98',
constructeur: 'manitou',
customValues: {
'Débit nominal (l/min)': 160,
'Pression max (bar)': 320,
},
},
{
name: 'Palier articulation flèche',
reference: 'BRG-UCP210-04',
typeCode: 'bearing',
modelCode: 'bearing-ucp210',
constructeur: 'skf',
customValues: {
'Référence fournisseur': 'SKF UCP210',
"Type d'étanchéité": '2RS',
},
},
],
},
];
for (const component of components) {
await createComponentHierarchy(machine.id, component, componentContext);
}
console.log('📦 Ajout des pièces de réserve machine...');
const spareMotor = await prisma.piece.create({
data: {
name: 'Moteur IE3 75 kW de secours',
reference: 'MTR-75-SPARE',
prix: new Prisma.Decimal('7900'),
machine: { connect: { id: machine.id } },
typePiece: { connect: { id: context.pieceTypes['electric-motor'].id } },
pieceModel: { connect: { id: context.pieceModels['motor-75kw'].id } },
constructeur: { connect: { id: context.constructeurs['sew'].id } },
typeMachinePieceRequirement: {
connect: { id: pieceRequirementMap.get('Moteurs de rechange')! },
},
customFieldValues: buildCustomFieldValues(
context.pieceTypes['electric-motor'].customFields,
{
'Puissance nominale (kW)': 75,
'Tension (V)': 400,
"Indice de protection": 'IP55',
},
),
},
});
await prisma.piece.create({
data: {
name: 'Capteur vitesse M12 de secours',
reference: 'SNS-VIT-SPARE-01',
prix: new Prisma.Decimal('190'),
machine: { connect: { id: machine.id } },
typePiece: { connect: { id: context.pieceTypes['speed-sensor'].id } },
pieceModel: { connect: { id: context.pieceModels['sensor-speed-m12'].id } },
constructeur: { connect: { id: context.constructeurs['ifm'].id } },
typeMachinePieceRequirement: {
connect: { id: pieceRequirementMap.get('Capteurs de vitesse de secours')! },
},
customFieldValues: buildCustomFieldValues(
context.pieceTypes['speed-sensor'].customFields,
{
'Type de sortie': 'PNP 4-20 mA',
'Plage de mesure (rpm)': 1200,
},
),
},
});
console.log(
`✅ Machine créée avec ${components.length} composants et pièces critiques enregistrées.`,
);
return {
machine,
spareMotor,
};
}
async function main() {
try {
await clearDatabaseExceptSitesAndProfiles();
const [site, constructeurs] = await Promise.all([
ensureDemoSite(),
createConstructeurs(),
]);
const { componentTypes, pieceTypes } = await createModelTypes();
const [pieceModels, componentModels, typeMachine] = await Promise.all([
createPieceModels(pieceTypes),
createComponentModels(componentTypes),
createTypeMachine(componentTypes, pieceTypes),
]);
await createMachineWithComponents(site.id, typeMachine, {
componentTypes,
componentModels,
pieceTypes,
pieceModels,
constructeurs,
});
console.log('🎉 Données de démonstration générées avec succès.');
} catch (error) {
console.error('❌ Erreur pendant la génération des données :', error);
process.exitCode = 1;
} finally {
await prisma.$disconnect();
}
}
main();