import { PrismaClient, Prisma, ModelCategory } from '@prisma/client'; const prisma = new PrismaClient(); type CustomFieldSpec = { name: string; type: 'string' | 'number' | 'boolean' | 'date' | 'select'; 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; }; type ComponentInstance = { name: string; reference?: string; prix?: string; typeCode: string; requirementLabel?: string; modelCode: string; constructeur?: string; customValues?: Record; pieces?: ComponentPieceInstance[]; children?: ComponentInstance[]; }; type TypeMachineDefinition = { code: string; name: string; description: string; category: string; maintenanceFrequency: string; specifications: Prisma.InputJsonValue; customFields: CustomFieldSpec[]; componentRequirements: { label: string; typeCode: string; minCount: number; maxCount?: number; required: boolean; }[]; pieceRequirements?: { label: string; typeCode: string; minCount: number; maxCount?: number; required: boolean; }[]; }; type MachineBuildSpec = { code: string; typeMachineCode: string; name: string; reference: string; prix: string; constructeurKey: string; customFieldValues: Record; components: ComponentInstance[]; sparePieces?: (ComponentPieceInstance & { requirementLabel?: string })[]; }; type TypeMachineRecord = Prisma.TypeMachineGetPayload<{ include: { customFields: true; componentRequirements: true; pieceRequirements: true; }; }>; const componentTypeDefinitions: ComponentTypeDefinition[] = [ { code: 'motor-drive', name: 'Groupe moteur', description: 'Motorisation asynchrone montée sur bride pour entraînements industriels.', customFields: [ { name: 'Puissance nominale (kW)', type: 'number', required: true }, { name: 'Classe énergétique', type: 'select', defaultValue: 'IE3', options: ['IE2', 'IE3', 'IE4'], }, { name: "Indice de protection", type: 'select', defaultValue: 'IP55', options: ['IP55', 'IP65', 'IP23'], }, ], }, { code: 'gearbox-assembly', name: 'Train réducteur', description: 'Réducteur industriel pour adaptation de vitesse.', customFields: [ { name: 'Rapport de réduction', type: 'select', defaultValue: '1:25', options: ['1:18', '1:24', '1:28', '1:32'], }, { name: 'Couple nominal (Nm)', type: 'number', required: true }, { name: 'Type de montage', type: 'select', options: ['À bride', 'À pattes', 'Sur arbre'], defaultValue: 'À bride', }, ], }, { code: 'bucket-head-section', name: "Tête d'élévateur", description: 'Module supérieur avec tambour moteur et trappes de visite.', customFields: [ { name: 'Largeur tambour (mm)', type: 'number', required: true }, { name: 'Type de revêtement', type: 'select', options: ['Caoutchouc rainuré', 'Céramique', 'Acier lisse'], defaultValue: 'Caoutchouc rainuré', }, { name: 'Nombre de trappes', type: 'number' }, ], }, { code: 'bucket-boot-section', name: "Pied d'élévateur", description: 'Module inférieur avec trémie et organes de tension.', customFields: [ { name: 'Capacité trémie (L)', type: 'number', required: true }, { name: 'Mode de tension', type: 'select', options: ['Vis manuelle', 'Contrepoids', 'Hydraulique'], defaultValue: 'Vis manuelle', }, { name: 'Système de nettoyage', type: 'select', options: ['Grattoirs', 'Balais', 'Vide-pied'], defaultValue: 'Grattoirs', }, ], }, { code: 'bucket-leg-section', name: 'Tronçon de gaine', description: 'Section intermédiaire de gaine pour élévateur.', customFields: [ { name: 'Hauteur section (m)', type: 'number', required: true }, { name: 'Type de gaine', type: 'select', options: ['Boulonnée', 'Soudée', 'Renforcée'], defaultValue: 'Boulonnée', }, ], }, { code: 'belt-drive-station', name: "Station d'entraînement", description: 'Station de tête pour convoyeur à bande.', customFields: [ { name: 'Type de tambour', type: 'select', options: ['Caoutchouc rainuré', 'Métallique', 'Céramique'], defaultValue: 'Caoutchouc rainuré', }, { name: 'Système de tension', type: 'select', options: ['Vis manuelle', 'Hydraulique', 'Pneumatique'], defaultValue: 'Vis manuelle', }, ], }, { code: 'belt-tail-station', name: 'Station de retour', description: 'Tambour de retour et système de nettoyage de bande.', customFields: [ { name: 'Nettoyeur principal', type: 'select', options: ['Racleur PU', 'Brosse acier', 'Racleur secondaire'], defaultValue: 'Racleur PU', }, { name: 'Diamètre tambour (mm)', type: 'number', required: true }, ], }, { code: 'belt-support-frame', name: 'Ossature convoyeur', description: 'Structure intermédiaire et rouleaux porteurs.', customFields: [ { name: 'Longueur (m)', type: 'number', required: true }, { name: 'Nombre de rouleaux', type: 'number', required: true }, { name: 'Type de châssis', type: 'select', options: ['Treillis', 'Caisson', 'Portique'], defaultValue: 'Treillis', }, ], }, { code: 'gravity-vibration-deck', name: 'Plateau vibrant', description: 'Plateau densimétrique pour séparation des grains.', customFields: [ { name: 'Type de plateau', type: 'select', options: ['Acier perforé', 'Inox poli', 'Composite'], defaultValue: 'Acier perforé', }, { name: 'Fréquence de vibration (Hz)', type: 'number', required: true }, { name: 'Inclinaison plateau (°)', type: 'number' }, ], }, { code: 'ventilation-fan', name: 'Ventilateur process', description: "Ventilateur d'aspiration ou d'extraction pour ligne céréalière.", customFields: [ { name: 'Débit (m³/h)', type: 'number', required: true }, { name: 'Type de roue', type: 'select', options: ['Axiale', 'Centrifuge', 'Mixte'], defaultValue: 'Centrifuge', }, { name: 'Vitesse nominale (rpm)', type: 'number' }, ], }, { code: 'control-panel', name: 'Armoire de contrôle', description: 'Armoire électrique pilotant un équipement ou une machine.', customFields: [ { name: 'Automate principal', type: 'select', required: true, defaultValue: 'Schneider Modicon M340', options: ['Schneider Modicon M340', 'Siemens S7-1500', 'Schneider Modicon M221'], }, { name: 'Année de mise à jour', type: 'number' }, { name: "Indice de protection", type: 'select', defaultValue: 'IP55', options: ['IP55', 'IP65', 'IP54'], }, ], }, { code: 'burner-module', name: 'Module brûleur', description: 'Module de combustion alimentant un séchoir en air chaud.', customFields: [ { name: 'Puissance thermique (kW)', type: 'number', required: true }, { name: 'Type de carburant', type: 'select', defaultValue: 'Gaz naturel', options: ['Gaz naturel', 'Biomasse', 'Fioul léger'], }, { name: "Système d'allumage", type: 'select', defaultValue: 'Double électrode', options: ['Double électrode', 'Brûleur pilote', 'Allumeur électronique'], }, ], }, { code: 'dryer-column-segment', name: 'Segment de colonne', description: 'Module de colonne de séchage empilable.', customFields: [ { name: 'Hauteur segment (m)', type: 'number', required: true }, { name: 'Zone de séchage', type: 'select', options: ['Échauffage', 'Tempe', 'Refroidissement'], defaultValue: 'Échauffage', }, { name: 'Capteurs intégrés', type: 'boolean', defaultValue: 'true' }, ], }, { code: 'dust-filter', name: 'Filtre à poussière', description: 'Filtre à manches ou cyclone pour dépoussiérage.', customFields: [ { name: 'Efficacité de filtration (%)', type: 'number', required: true }, { name: 'Type de média filtrant', type: 'select', options: ['Polyester', 'Fibre de verre', 'Polypropylène'], defaultValue: 'Polyester', }, { name: 'Nombre de cartouches', type: 'number' }, ], }, { code: 'screw-trough-section', name: 'Caisson de vis', description: 'Tronçon de vis sans fin avec palier intermédiaire.', customFields: [ { name: 'Longueur (m)', type: 'number', required: true }, { name: 'Diamètre vis (mm)', type: 'number', required: true }, { name: 'Matériau', type: 'select', options: ['Acier peint', 'Acier inoxydable', 'Galvanisé'], defaultValue: 'Acier peint', }, ], }, { code: 'screw-inlet-hopper', name: "Trémie d'alimentation", description: 'Trémie de reprise amont pour vis sans fin.', customFields: [ { name: 'Capacité (L)', type: 'number', required: true }, { name: 'Type de grille', type: 'select', options: ['Grille lisse', 'Grille anti-gravats', 'Grille magnétique'], defaultValue: 'Grille anti-gravats', }, ], }, { code: 'screw-outlet-chute', name: 'Goulotte de sortie', description: 'Sortie aval avec vanne de réglage.', customFields: [ { name: 'Type de vanne', type: 'select', options: ['Guillotine', 'Papillon', 'By-pass'], defaultValue: 'Guillotine', }, { name: "Orientation (°)", type: 'number' }, ], }, { code: 'weigh-load-frame', name: 'Cadre peseur', description: 'Structure équipée de capteurs de pesage.', customFields: [ { name: 'Capacité nominale (kg)', type: 'number', required: true }, { name: 'Nombre de capteurs', type: 'number', required: true }, { name: 'Protection IP', type: 'select', options: ['IP54', 'IP65', 'IP67'], defaultValue: 'IP65', }, ], }, { code: 'weigh-discharge-gate', name: 'Vanne de vidange', description: 'Organe de vidange motorisé pour benne peseuse.', customFields: [ { name: "Type d'actionneur", type: 'select', options: ['Hydraulique', 'Motoréducteur', 'Pneumatique'], defaultValue: 'Hydraulique', }, { name: "Temps d'ouverture (s)", type: 'number' }, ], }, { code: 'hydraulic-power-pack', name: 'Groupe hydraulique', description: 'Groupe hydraulique alimentant vérins et accessoires.', customFields: [ { name: 'Débit nominal (l/min)', type: 'number', required: true }, { name: 'Pression max (bar)', type: 'number', required: true }, { name: 'Type de pompe', type: 'select', options: ['Piston axial', 'Palette', 'Engrenages'], defaultValue: 'Piston axial', }, ], }, { code: 'telehandler-boom', name: 'Flèche télescopique', description: 'Flèche et berceau de levage pour chariot télescopique.', customFields: [ { name: 'Hauteur max (m)', type: 'number', required: true }, { name: 'Sections télescopiques', type: 'number', required: true }, { name: 'Type de guidage', type: 'select', options: ['Galets', 'Patins composites'], defaultValue: 'Galets', }, ], }, { code: 'telehandler-cab-module', name: 'Cabine opérateur', description: 'Cabine pressurisée avec commandes.', customFields: [ { name: 'Type de cabine', type: 'select', options: ['Standard', 'Premium climatisée', 'Haute visibilité'], defaultValue: 'Premium climatisée', }, { name: 'Climatisation', type: 'boolean', defaultValue: 'true' }, { name: 'Nombre de caméras', type: 'number' }, ], }, { code: 'telehandler-attachment-carrier', name: 'Support d’outils', description: 'Plaque porte-outils et attelage rapide.', customFields: [ { name: "Type d'attache", type: 'select', options: ['Fourches FEM', 'Attache Euro', 'Attache Manitou'], defaultValue: 'Attache Manitou', }, { name: 'Capacité nominale (t)', type: 'number', required: true }, ], }, ]; const pieceTypeDefinitions: PieceTypeDefinition[] = [ { code: 'hex-screw', name: 'Vis hexagonale', description: 'Visserie pour assemblages mécaniques.', customFields: [ { name: 'Diamètre (mm)', type: 'number', required: true }, { name: 'Longueur (mm)', type: 'number', required: true }, { name: 'Classe acier', type: 'select', options: ['8.8', '10.9', '12.9'], defaultValue: '8.8', }, ], }, { code: 'lock-washer', name: 'Rondelle Grower', description: 'Rondelle anti-desserrage.', customFields: [ { name: 'Diamètre (mm)', type: 'number', required: true }, { name: 'Finition', type: 'select', options: ['Zinguée', 'Inox', 'Noire'], defaultValue: 'Inox', }, ], }, { code: 'flat-gasket', name: 'Joint plat', description: 'Joint pour brides et trappes de maintenance.', customFields: [ { name: 'Matière', type: 'select', options: ['NBR', 'PTFE', 'Fibre compressée'], defaultValue: 'NBR', }, { name: 'Épaisseur (mm)', type: 'number', required: true }, ], }, { code: 'drive-belt', name: 'Courroie', description: 'Courroie transporteuse ou élévatrice.', customFields: [ { name: 'Largeur (mm)', type: 'number', required: true }, { name: 'Matériau', type: 'select', options: ['Caoutchouc nitrile', 'Polyuréthane', 'PVC'], defaultValue: 'Caoutchouc nitrile', }, ], }, { code: 'roller-bearing', name: 'Roulement', description: 'Roulement à semelle ou palier.', customFields: [ { name: 'Série', type: 'select', options: ['UCP', 'UCFL', 'UCT'], defaultValue: 'UCP', }, { name: "Type d'étanchéité", type: 'select', options: ['ZZ', '2RS'], defaultValue: '2RS', }, ], }, { code: 'filter-cartridge', name: 'Cartouche filtrante', description: 'Cartouche de dépoussiérage.', customFields: [ { name: 'Longueur (mm)', type: 'number', required: true }, { name: 'Média filtrant', type: 'select', options: ['Polyester', 'Fibre de verre', 'Nomex'], defaultValue: 'Polyester', }, ], }, { code: 'speed-sensor', name: 'Capteur de vitesse', description: 'Capteur inductif pour surveillance de rotation.', customFields: [ { name: 'Type de sortie', type: 'select', options: ['PNP 4-20 mA', 'PNP Tout ou rien'], defaultValue: 'PNP 4-20 mA', }, { name: 'Plage de mesure (rpm)', type: 'number', required: true }, ], }, { code: 'temperature-probe', name: 'Sonde de température', description: 'Sonde PT100 pour surveillance du séchage.', customFields: [ { name: 'Type', type: 'select', options: ['PT100 classe A', 'PT100 classe B'], defaultValue: 'PT100 classe A', }, { name: 'Longueur tige (mm)', type: 'number', required: true }, ], }, { code: 'fuse-cartridge', name: 'Fusible', description: 'Fusible cylindrique pour protection électrique.', customFields: [ { name: 'Calibre (A)', type: 'number', required: true }, { name: 'Type', type: 'select', options: ['gG', 'aM'], defaultValue: 'gG', }, ], }, { code: 'load-cell', name: 'Capteur de pesage', description: 'Capteur de pesage pour benne peseuse.', customFields: [ { name: 'Capacité (kg)', type: 'number', required: true }, { name: 'Type de connexion', type: 'select', options: ['Câble 4 fils', 'Câble 6 fils'], defaultValue: 'Câble 6 fils', }, ], }, { code: 'lubrication-cartridge', name: 'Cartouche de graisse', description: 'Cartouche pour point de graissage automatique.', customFields: [ { name: 'Volume (cm³)', type: 'number', required: true }, { name: 'Grade de graisse', type: 'select', options: ['NLGI 1', 'NLGI 2'], defaultValue: 'NLGI 2', }, ], }, { code: 'hydraulic-hose', name: 'Flexible hydraulique', description: 'Flexible haute pression pour circuit hydraulique.', customFields: [ { name: 'Pression max (bar)', type: 'number', required: true }, { name: 'Type de renfort', type: 'select', options: ['2 tresses acier', '4 nappes acier'], defaultValue: '2 tresses acier', }, { name: 'Longueur (mm)', type: 'number', required: true }, ], }, ]; const pieceModelDefinitions: PieceModelDefinition[] = [ { code: 'screw-m12x80', name: 'Vis M12x80 8.8', description: 'Vis tête hexagonale pour charpente.', typeCode: 'hex-screw', structure: { standard: 'ISO 4014' }, }, { code: 'screw-m10x60', name: 'Vis M10x60 10.9', description: 'Vis haute résistance pour convoyeur.', typeCode: 'hex-screw', }, { code: 'screw-m8x30', name: 'Vis M8x30 inox', description: 'Visserie inox pour accessoires.', typeCode: 'hex-screw', }, { code: 'washer-grower-12', name: 'Rondelle Grower Ø12', description: 'Rondelle de sécurité inox.', typeCode: 'lock-washer', }, { code: 'washer-grower-10', name: 'Rondelle Grower Ø10', description: 'Rondelle pour visserie M10.', typeCode: 'lock-washer', }, { code: 'gasket-ht-200', name: 'Joint haute température 200°C', description: 'Joint fibre compressée pour trappe.', typeCode: 'flat-gasket', }, { code: 'belt-hd-800', name: 'Courroie 800 mm Heavy Duty', description: 'Courroie caoutchouc nitrile 800 mm.', typeCode: 'drive-belt', }, { code: 'belt-hd-650', name: 'Courroie 650 mm Agro', description: 'Courroie polyuréthane 650 mm.', typeCode: 'drive-belt', }, { code: 'bearing-ucp210', name: 'Palier UCP210', description: 'Roulement semelle fonte.', typeCode: 'roller-bearing', }, { code: 'bearing-ucfl207', name: 'Palier UCFL207', description: 'Roulement bride deux trous.', typeCode: 'roller-bearing', }, { code: 'filter-dust-610', name: 'Cartouche filtre 610 mm', description: 'Cartouche polyester 610 mm.', typeCode: 'filter-cartridge', }, { code: 'filter-dust-480', name: 'Cartouche filtre 480 mm', description: 'Cartouche polyester 480 mm.', typeCode: 'filter-cartridge', }, { code: 'sensor-speed-m12', name: 'Capteur vitesse M12', description: 'Capteur inductif M12 PNP 4-20 mA.', typeCode: 'speed-sensor', }, { code: 'sensor-speed-m18', name: 'Capteur vitesse M18', description: 'Capteur inductif M18 PNP.', typeCode: 'speed-sensor', }, { code: 'temp-probe-pt100', name: 'Sonde PT100 300 mm', description: 'Sonde PT100 classe A tige 300 mm.', typeCode: 'temperature-probe', }, { code: 'temp-probe-pt100-short', name: 'Sonde PT100 200 mm', description: 'Sonde PT100 compacte.', typeCode: 'temperature-probe', }, { code: 'fuse-gg-25a', name: 'Fusible gG 25A', description: 'Fusible protection puissance 25A.', typeCode: 'fuse-cartridge', }, { code: 'fuse-gg-40a', name: 'Fusible gG 40A', description: 'Fusible protection 40A.', typeCode: 'fuse-cartridge', }, { code: 'load-cell-5t', name: 'Capteur pesage 5T', description: 'Capteur compression 5 tonnes.', typeCode: 'load-cell', }, { code: 'grease-cartridge-400', name: 'Cartouche graisse 400g', description: 'Cartouche graisse NLGI2 400g.', typeCode: 'lubrication-cartridge', }, { code: 'hydraulic-hose-2w', name: 'Flexible 2 tresses 420 bar', description: 'Flexible 2 tresses acier 420 bar.', typeCode: 'hydraulic-hose', }, ]; const componentModelDefinitions: ComponentModelDefinition[] = [ { code: 'motor-drive-75', name: 'Moteur 75 kW IE3', description: 'Moteur IE3 75 kW IP55.', typeCode: 'motor-drive', structure: { recommendedCustomFields: { 'Puissance nominale (kW)': '75', 'Classe énergétique': 'IE3', "Indice de protection": 'IP55', }, }, }, { code: 'motor-drive-55', name: 'Moteur 55 kW IE3', description: 'Motorisation ligne aval.', typeCode: 'motor-drive', }, { code: 'motor-drive-45', name: 'Moteur 45 kW IE3', description: 'Motorisation convoyeur principal.', typeCode: 'motor-drive', }, { code: 'motor-drive-37', name: 'Moteur 37 kW IE3', description: 'Motorisation convoyeur secondaire.', typeCode: 'motor-drive', }, { code: 'motor-drive-18', name: 'Moteur 18.5 kW IE3', description: 'Motorisation vis sans fin.', typeCode: 'motor-drive', }, { code: 'motor-drive-15', name: 'Moteur 15 kW IE3', description: 'Motorisation vis compact.', typeCode: 'motor-drive', }, { code: 'motor-drive-110', name: 'Moteur 110 kW IE3', description: 'Motorisation séchoir.', typeCode: 'motor-drive', }, { code: 'gearbox-flender', name: 'Réducteur Flender 3200 Nm', description: 'Réducteur à couple élevé.', typeCode: 'gearbox-assembly', }, { code: 'gearbox-bonfiglioli', name: 'Réducteur Bonfiglioli TA', description: 'Réducteur montage sur arbre.', typeCode: 'gearbox-assembly', }, { code: 'gearbox-sew', name: 'Réducteur SEW K', description: 'Réducteur coaxial pour vis.', typeCode: 'gearbox-assembly', }, { code: 'bucket-head-120', name: 'Tête élévateur 800 mm', description: 'Tête renforcée 800 mm.', typeCode: 'bucket-head-section', }, { code: 'bucket-head-95', name: 'Tête élévateur 650 mm', description: 'Tête compacte 650 mm.', typeCode: 'bucket-head-section', }, { code: 'bucket-boot-heavy', name: 'Pied élévateur renforcé', description: 'Pied avec tension à vis.', typeCode: 'bucket-boot-section', }, { code: 'bucket-boot-compact', name: 'Pied élévateur compact', description: 'Pied compact avec tension hydraulique.', typeCode: 'bucket-boot-section', }, { code: 'bucket-leg-3m', name: 'Tronçon 3 m', description: 'Gaine 3 mètres renforcée.', typeCode: 'bucket-leg-section', }, { code: 'bucket-leg-2-5m', name: 'Tronçon 2,5 m', description: 'Gaine 2,5 mètres compacte.', typeCode: 'bucket-leg-section', }, { code: 'belt-drive-800', name: "Station entraînement 800", description: 'Station tête 800 mm.', typeCode: 'belt-drive-station', }, { code: 'belt-drive-650', name: "Station entraînement 650", description: 'Station tête 650 mm.', typeCode: 'belt-drive-station', }, { code: 'belt-tail-800', name: 'Station retour 800', description: 'Retour 800 mm avec racleur.', typeCode: 'belt-tail-station', }, { code: 'belt-tail-650', name: 'Station retour 650', description: 'Retour 650 mm compact.', typeCode: 'belt-tail-station', }, { code: 'belt-frame-18m', name: 'Ossature 18 m', description: 'Châssis convoyeur 18 m.', typeCode: 'belt-support-frame', }, { code: 'belt-frame-25m', name: 'Ossature 25 m', description: 'Châssis convoyeur 25 m.', typeCode: 'belt-support-frame', }, { code: 'gravity-deck-120', name: 'Plateau densimétrique 120', description: 'Plateau haute capacité.', typeCode: 'gravity-vibration-deck', }, { code: 'gravity-deck-80', name: 'Plateau densimétrique 80', description: 'Plateau compact.', typeCode: 'gravity-vibration-deck', }, { code: 'fan-process-45', name: 'Ventilateur 45 kW', description: 'Ventilateur centrifuge 45 kW.', typeCode: 'ventilation-fan', }, { code: 'fan-process-30', name: 'Ventilateur 30 kW', description: 'Ventilateur centrifuge 30 kW.', typeCode: 'ventilation-fan', }, { code: 'control-panel-m340', name: 'Armoire Schneider M340', description: 'Armoire Schneider Electric.', typeCode: 'control-panel', }, { code: 'control-panel-s7', name: 'Armoire Siemens S7', description: 'Armoire Siemens S7-1500.', typeCode: 'control-panel', }, { code: 'burner-module-3mw', name: 'Brûleur gaz 3 MW', description: 'Brûleur gaz modulant.', typeCode: 'burner-module', }, { code: 'burner-module-2mw', name: 'Brûleur biomasse 2 MW', description: 'Brûleur biomasse compact.', typeCode: 'burner-module', }, { code: 'dryer-column-2m', name: 'Segment colonne 2 m', description: 'Segment de colonne zone chaude.', typeCode: 'dryer-column-segment', }, { code: 'dryer-column-1-5m', name: 'Segment colonne 1,5 m', description: 'Segment zone refroidissement.', typeCode: 'dryer-column-segment', }, { code: 'dust-filter-cyclone', name: 'Filtre cyclone 610', description: 'Filtre cyclone 6 cartouches.', typeCode: 'dust-filter', }, { code: 'dust-filter-compact', name: 'Filtre compact 480', description: 'Filtre compact 4 cartouches.', typeCode: 'dust-filter', }, { code: 'screw-trough-200', name: 'Caisson vis 200', description: 'Caisson pour vis 200 mm.', typeCode: 'screw-trough-section', }, { code: 'screw-trough-160', name: 'Caisson vis 160', description: 'Caisson pour vis 160 mm.', typeCode: 'screw-trough-section', }, { code: 'screw-inlet-200', name: 'Trémie alimentation 200', description: 'Trémie 200 l anti-gravats.', typeCode: 'screw-inlet-hopper', }, { code: 'screw-inlet-160', name: 'Trémie alimentation 160', description: 'Trémie 160 l compacte.', typeCode: 'screw-inlet-hopper', }, { code: 'screw-outlet-vanne', name: 'Goulotte vanne guillotine', description: 'Goulotte sortie vanne guillotine.', typeCode: 'screw-outlet-chute', }, { code: 'screw-outlet-flap', name: 'Goulotte clapet by-pass', description: 'Goulotte sortie clapet.', typeCode: 'screw-outlet-chute', }, { code: 'weigh-frame-5t', name: 'Cadre peseur 5T', description: 'Cadre peseur 5 tonnes.', typeCode: 'weigh-load-frame', }, { code: 'weigh-frame-3t', name: 'Cadre peseur 3T', description: 'Cadre peseur 3 tonnes.', typeCode: 'weigh-load-frame', }, { code: 'weigh-gate-hydraulic', name: 'Vanne hydraulique', description: 'Vanne hydraulique ouverture rapide.', typeCode: 'weigh-discharge-gate', }, { code: 'weigh-gate-screw', name: 'Vanne vis motorisée', description: 'Vanne motoréducteur vis.', typeCode: 'weigh-discharge-gate', }, { code: 'hydraulic-pack-tele', name: 'Groupe hydraulique 140 l/min', description: 'Groupe hydraulique Manitou.', typeCode: 'hydraulic-power-pack', }, { code: 'tele-boom-8m', name: 'Flèche télescopique 8 m', description: 'Flèche 4 sections 8 m.', typeCode: 'telehandler-boom', }, { code: 'tele-cab-premium', name: 'Cabine premium climatisée', description: 'Cabine Manitou climatisée.', typeCode: 'telehandler-cab-module', }, { code: 'tele-carrier-quick', name: 'Attache rapide universelle', description: 'Support d’outils Manitou.', typeCode: 'telehandler-attachment-carrier', }, ]; const constructeurDefinitions: ConstructeurDefinition[] = [ { key: 'buhler', name: 'Bühler Grain Systems', email: 'contact@buhlergroup.com', phone: '+41 71 955 11 11', }, { key: 'agritech', name: 'Agritech Elevators', email: 'info@agritech.fr', phone: '+33 4 78 12 34 56', }, { key: 'valmont', name: 'Valmont Handling', email: 'sales@valmont.fr', phone: '+33 3 88 77 41 20', }, { key: 'agridry', name: 'Agridry Systems', email: 'support@agridry.eu', phone: '+33 2 41 52 78 00', }, { key: 'agrifan', name: 'AgriFan Ventilation', email: 'contact@agrifan.fr', phone: '+33 2 44 55 12 32', }, { key: 'manitou', name: 'Manitou Group', email: 'support@manitou-group.com', phone: '+33 2 40 09 10 11', }, { key: 'sew', name: 'SEW-Eurodrive', email: 'info@sew-eurodrive.fr', phone: '+33 4 72 24 60 00', }, { key: 'flender', name: 'Flender GmbH', email: 'contact@flender.com', phone: '+49 203 998 0', }, { key: 'bonfiglioli', name: 'Bonfiglioli Riduttori', email: 'sales@bonfiglioli.com', phone: '+39 051 647 3111', }, { key: 'poclain', name: 'Poclain Hydraulics', email: 'support@poclain-hydraulics.com', phone: '+33 3 44 31 74 00', }, { key: 'ifm', name: 'IFM Electronic', email: 'contact@ifm.com', phone: '+33 1 69 11 37 00', }, { key: 'skf', name: 'SKF France', email: 'support@skf.com', phone: '+33 4 37 24 64 00', }, ]; const typeMachineDefinitions: TypeMachineDefinition[] = [ { code: 'bucket-elevator', name: 'Élévateur à godets industriel', description: 'Machine de manutention verticale pour élévation de céréales.', category: 'Triage & convoyage', maintenanceFrequency: "Inspection journalière des trappes, graissage hebdomadaire des paliers, contrôle courroie mensuel.", specifications: { zone: 'Réception', instrumentation: ['Capteur vitesse', 'Capteur niveau'], }, customFields: [ { name: 'Capacité nominale (t/h)', type: 'number', required: true }, { name: 'Hauteur de levage (m)', type: 'number', required: true }, { name: 'Produit traité', type: 'select', options: ['Blé tendre', 'Orge brassicole', 'Maïs grain'], defaultValue: 'Blé tendre', required: true, }, { name: 'Date de mise en service', type: 'date', required: true }, ], componentRequirements: [ { label: "Tête d'élévateur", typeCode: 'bucket-head-section', minCount: 1, maxCount: 1, required: true, }, { label: "Pied d'élévateur", typeCode: 'bucket-boot-section', minCount: 1, maxCount: 1, required: true, }, { label: 'Tronçons de gaine', typeCode: 'bucket-leg-section', minCount: 2, required: true, }, { label: 'Motorisation principale', typeCode: 'motor-drive', minCount: 1, required: true, }, { label: 'Réducteur principal', typeCode: 'gearbox-assembly', minCount: 1, required: true, }, { label: 'Armoire locale', typeCode: 'control-panel', minCount: 1, maxCount: 1, required: false, }, ], pieceRequirements: [ { label: 'Courroie élévatrice', typeCode: 'drive-belt', minCount: 1, required: true, }, { label: 'Capteur de vitesse', typeCode: 'speed-sensor', minCount: 1, required: false, }, { label: 'Kit visserie structure', typeCode: 'hex-screw', minCount: 1, required: false, }, ], }, { code: 'belt-conveyor', name: 'Convoyeur à bande industriel', description: 'Convoyeur horizontal ou incliné pour transfert de grains.', category: 'Triage & convoyage', maintenanceFrequency: 'Contrôle visuel quotidien, réglage de bande hebdomadaire, révision annuelle.', specifications: { zone: 'Transfert', supports: ['Passerelle', 'Structure acier'], }, customFields: [ { name: 'Débit (t/h)', type: 'number', required: true }, { name: 'Longueur (m)', type: 'number', required: true }, { name: 'Localisation', type: 'select', options: ['Réception', 'Nettoyage', 'Expédition'], defaultValue: 'Réception', }, ], componentRequirements: [ { label: "Station d'entraînement", typeCode: 'belt-drive-station', minCount: 1, maxCount: 1, required: true, }, { label: 'Station de retour', typeCode: 'belt-tail-station', minCount: 1, maxCount: 1, required: true, }, { label: 'Ossature intermédiaire', typeCode: 'belt-support-frame', minCount: 1, required: true, }, { label: 'Motorisation convoyeur', typeCode: 'motor-drive', minCount: 1, required: true, }, { label: 'Réducteur convoyeur', typeCode: 'gearbox-assembly', minCount: 1, required: true, }, { label: 'Coffret de commande', typeCode: 'control-panel', minCount: 1, required: false, }, ], pieceRequirements: [ { label: 'Bande transporteuse', typeCode: 'drive-belt', minCount: 1, required: true, }, { label: 'Paliers supports', typeCode: 'roller-bearing', minCount: 2, required: false, }, { label: 'Visserie ossature', typeCode: 'hex-screw', minCount: 1, required: false, }, ], }, { code: 'gravity-separator', name: 'Table densimétrique', description: 'Table vibrante pour séparation par densité.', category: 'Nettoyage', maintenanceFrequency: 'Nettoyage tamis quotidien, contrôle vibrateurs hebdomadaire.', specifications: { zone: 'Nettoyage fin', aspiration: true, }, customFields: [ { name: 'Capacité de tri (t/h)', type: 'number', required: true }, { name: 'Produit traité', type: 'select', options: ['Blé', 'Orge', 'Tournesol'], defaultValue: 'Blé', }, { name: 'Date de mise en service', type: 'date', required: true }, ], componentRequirements: [ { label: 'Plateau vibrant', typeCode: 'gravity-vibration-deck', minCount: 1, required: true, }, { label: 'Ventilateur aspiration', typeCode: 'ventilation-fan', minCount: 1, required: true, }, { label: 'Armoire de réglage', typeCode: 'control-panel', minCount: 1, required: true, }, ], pieceRequirements: [ { label: 'Capteur vibration', typeCode: 'speed-sensor', minCount: 1, required: false, }, { label: 'Kit visserie plateau', typeCode: 'hex-screw', minCount: 1, required: false, }, { label: 'Cartouche aspiration', typeCode: 'filter-cartridge', minCount: 1, required: false, }, ], }, { code: 'grain-dryer', name: 'Séchoir à grains continu', description: 'Système de séchage continu haute capacité.', category: 'Séchage', maintenanceFrequency: 'Contrôle brûleur hebdomadaire, nettoyage filtre et vérification ventilateurs mensuels.', specifications: { bâtiment: 'Tour de séchage', energie: ['Gaz naturel', 'Électricité'], }, customFields: [ { name: 'Capacité sèche (t/h)', type: 'number', required: true }, { name: 'Mode d’alimentation', type: 'select', options: ['Élévateur principal', 'Vis de reprise'], defaultValue: 'Élévateur principal', }, { name: 'Date de mise en service', type: 'date', required: true }, ], componentRequirements: [ { label: 'Module brûleur', typeCode: 'burner-module', minCount: 1, required: true, }, { label: 'Colonnes de séchage', typeCode: 'dryer-column-segment', minCount: 2, required: true, }, { label: 'Ventilation process', typeCode: 'ventilation-fan', minCount: 1, required: true, }, { label: 'Filtre poussières', typeCode: 'dust-filter', minCount: 1, required: true, }, { label: 'Armoire de pilotage', typeCode: 'control-panel', minCount: 1, required: true, }, ], pieceRequirements: [ { label: 'Sondes température', typeCode: 'temperature-probe', minCount: 2, required: false, }, { label: 'Joints haute température', typeCode: 'flat-gasket', minCount: 1, required: false, }, { label: 'Cartouches dépoussiéreur', typeCode: 'filter-cartridge', minCount: 2, required: false, }, ], }, { code: 'screw-conveyor', name: 'Vis de reprise céréales', description: 'Vis sans fin pour reprise et rechargement des silos.', category: 'Convoyage', maintenanceFrequency: 'Graissage paliers hebdomadaire, inspection trémie mensuelle.', specifications: { position: ['Sous cellules', 'Sortie séchoir'], }, customFields: [ { name: 'Diamètre vis (mm)', type: 'number', required: true }, { name: 'Inclinaison (°)', type: 'number' }, { name: 'Vitesse (rpm)', type: 'number' }, ], componentRequirements: [ { label: 'Caisson principal', typeCode: 'screw-trough-section', minCount: 1, required: true, }, { label: "Trémie d'alimentation", typeCode: 'screw-inlet-hopper', minCount: 1, required: true, }, { label: 'Goulotte de sortie', typeCode: 'screw-outlet-chute', minCount: 1, required: true, }, { label: 'Motorisation vis', typeCode: 'motor-drive', minCount: 1, required: true, }, { label: 'Réducteur vis', typeCode: 'gearbox-assembly', minCount: 1, required: true, }, ], pieceRequirements: [ { label: 'Paliers de ligne', typeCode: 'roller-bearing', minCount: 2, required: false, }, { label: 'Kit visserie caisson', typeCode: 'hex-screw', minCount: 1, required: false, }, { label: 'Cartouches de graisse', typeCode: 'lubrication-cartridge', minCount: 1, required: false, }, ], }, { code: 'weigh-hopper', name: 'Benne peseuse', description: 'Benne peseuse pour chargement camions ou big-bags.', category: 'Expédition', maintenanceFrequency: 'Vérification capteurs hebdomadaire, recalibrage trimestriel.', specifications: { utilisation: ['Chargement camion', 'Conditionnement big-bag'], }, customFields: [ { name: 'Capacité de pesée (kg)', type: 'number', required: true }, { name: 'Précision (%)', type: 'number', required: true, }, { name: 'Mode de vidange', type: 'select', options: ['Trappe motorisée', 'Vis doseuse', 'Vanne guillotine'], defaultValue: 'Trappe motorisée', }, ], componentRequirements: [ { label: 'Cadre peseur', typeCode: 'weigh-load-frame', minCount: 1, required: true, }, { label: 'Vanne de vidange', typeCode: 'weigh-discharge-gate', minCount: 1, required: true, }, { label: 'Coffret de pesage', typeCode: 'control-panel', minCount: 1, required: true, }, ], pieceRequirements: [ { label: 'Capteurs de pesage', typeCode: 'load-cell', minCount: 2, required: true, }, { label: 'Fusibles de protection', typeCode: 'fuse-cartridge', minCount: 1, required: false, }, { label: 'Joint trappe', typeCode: 'flat-gasket', minCount: 1, required: false, }, ], }, { code: 'telehandler', name: 'Chariot télescopique logistique', description: 'Chariot télescopique dédié aux manutentions céréalières.', category: 'Logistique', maintenanceFrequency: 'Graissage hebdomadaire, contrôle hydraulique mensuel.', specifications: { yardArea: 'Cour logistique', rotation: '3 équipes', }, customFields: [ { name: 'Usage principal', type: 'select', options: ['Chargement camions', 'Gestion big-bags', 'Maintenance silo'], defaultValue: 'Chargement camions', }, { name: 'Lieu de stationnement', type: 'select', options: ['Hangar nord', 'Cour extérieure', 'Atelier maintenance'], defaultValue: 'Hangar nord', }, { name: "Année d'achat", type: 'number', required: true }, ], componentRequirements: [ { label: 'Flèche télescopique', typeCode: 'telehandler-boom', minCount: 1, required: true, }, { label: 'Groupe hydraulique', typeCode: 'hydraulic-power-pack', minCount: 1, required: true, }, { label: 'Groupe moteur', typeCode: 'motor-drive', minCount: 1, required: true, }, { label: 'Cabine opérateur', typeCode: 'telehandler-cab-module', minCount: 1, required: true, }, { label: 'Support d’outils', typeCode: 'telehandler-attachment-carrier', minCount: 1, required: true, }, ], pieceRequirements: [ { label: 'Flexibles hydrauliques', typeCode: 'hydraulic-hose', minCount: 2, required: false, }, { label: 'Fusibles cabine', typeCode: 'fuse-cartridge', minCount: 1, required: false, }, { label: 'Cartouches graissage', typeCode: 'lubrication-cartridge', minCount: 1, required: false, }, ], }, ]; const machineBuilds: MachineBuildSpec[] = [ { code: 'bucket-elevator-upstream', typeMachineCode: 'bucket-elevator', name: 'Élévateur amont Z400', reference: 'BE-Z400-01', prix: '58000', constructeurKey: 'agritech', customFieldValues: { 'Capacité nominale (t/h)': 120, 'Hauteur de levage (m)': 38, 'Produit traité': 'Blé tendre', 'Date de mise en service': new Date('2023-10-12'), }, components: [ { name: 'Tête haute Z400', reference: 'BE-TETE-400', prix: '18500', typeCode: 'bucket-head-section', requirementLabel: "Tête d'élévateur", modelCode: 'bucket-head-120', constructeur: 'agritech', customValues: { 'Largeur tambour (mm)': 820, 'Type de revêtement': 'Caoutchouc rainuré', 'Nombre de trappes': 3, }, pieces: [ { name: 'Kit visserie tête', reference: 'KIT-TETE-01', typeCode: 'hex-screw', modelCode: 'screw-m12x80', customValues: { 'Diamètre (mm)': 12, 'Longueur (mm)': 80, 'Classe acier': '8.8', }, }, { name: 'Rondelles de sécurité Ø12', reference: 'RDL-TETE-01', typeCode: 'lock-washer', modelCode: 'washer-grower-12', customValues: { 'Diamètre (mm)': 12, Finition: 'Inox', }, }, ], children: [ { name: 'Motorisation 75 kW', reference: 'MTR-75-EL1', typeCode: 'motor-drive', requirementLabel: 'Motorisation principale', modelCode: 'motor-drive-75', constructeur: 'sew', customValues: { 'Puissance nominale (kW)': 75, 'Classe énergétique': 'IE3', "Indice de protection": 'IP55', }, }, { name: 'Réducteur Flender 3200', reference: 'GBX-FL-01', typeCode: 'gearbox-assembly', requirementLabel: 'Réducteur principal', modelCode: 'gearbox-flender', constructeur: 'flender', customValues: { 'Rapport de réduction': '1:28', 'Couple nominal (Nm)': 3200, 'Type de montage': 'À bride', }, }, ], }, { name: 'Pied élévateur renforcé', reference: 'BE-PIED-400', prix: '14600', typeCode: 'bucket-boot-section', requirementLabel: "Pied d'élévateur", modelCode: 'bucket-boot-heavy', constructeur: 'agritech', customValues: { 'Capacité trémie (L)': 480, 'Mode de tension': 'Vis manuelle', 'Système de nettoyage': 'Grattoirs', }, pieces: [ { name: 'Joint trappe inspection', reference: 'JNT-PIED-01', typeCode: 'flat-gasket', modelCode: 'gasket-ht-200', customValues: { Matière: 'Fibre compressée', 'Épaisseur (mm)': 3, }, }, ], }, { name: 'Gaine intermédiaire 3 m - A', reference: 'BE-GAINE-1', typeCode: 'bucket-leg-section', requirementLabel: 'Tronçons de gaine', modelCode: 'bucket-leg-3m', constructeur: 'agritech', customValues: { 'Hauteur section (m)': 3, 'Type de gaine': 'Boulonnée', }, }, { name: 'Gaine intermédiaire 3 m - B', reference: 'BE-GAINE-2', typeCode: 'bucket-leg-section', requirementLabel: 'Tronçons de gaine', modelCode: 'bucket-leg-3m', constructeur: 'agritech', customValues: { 'Hauteur section (m)': 3, 'Type de gaine': 'Renforcée', }, }, { name: 'Armoire locale tête élévateur', reference: 'ARM-EL-01', prix: '7800', typeCode: 'control-panel', requirementLabel: 'Armoire locale', modelCode: 'control-panel-m340', constructeur: 'buhler', customValues: { 'Automate principal': 'Schneider Modicon M340', 'Année de mise à jour': 2023, "Indice de protection": 'IP55', }, pieces: [ { name: 'Fusible alimentation 25A', reference: 'FS-25A-EL', typeCode: 'fuse-cartridge', modelCode: 'fuse-gg-25a', customValues: { 'Calibre (A)': 25, Type: 'gG', }, }, ], }, ], sparePieces: [ { name: 'Courroie de rechange 800 mm', reference: 'SP-BELT-800', prix: '2200', typeCode: 'drive-belt', modelCode: 'belt-hd-800', constructeur: 'agritech', requirementLabel: 'Courroie élévatrice', customValues: { 'Largeur (mm)': 800, Matériau: 'Caoutchouc nitrile', }, }, { name: 'Capteur vitesse secours', reference: 'SP-SPEED-01', typeCode: 'speed-sensor', modelCode: 'sensor-speed-m12', constructeur: 'ifm', requirementLabel: 'Capteur de vitesse', customValues: { 'Type de sortie': 'PNP 4-20 mA', 'Plage de mesure (rpm)': 1200, }, }, { name: 'Jeu visserie structure', reference: 'SP-VISS-EL', typeCode: 'hex-screw', modelCode: 'screw-m12x80', requirementLabel: 'Kit visserie structure', customValues: { 'Diamètre (mm)': 12, 'Longueur (mm)': 80, 'Classe acier': '8.8', }, }, ], }, { code: 'bucket-elevator-downstream', typeMachineCode: 'bucket-elevator', name: 'Élévateur aval Z320', reference: 'BE-Z320-02', prix: '49700', constructeurKey: 'agritech', customFieldValues: { 'Capacité nominale (t/h)': 95, 'Hauteur de levage (m)': 32, 'Produit traité': 'Orge brassicole', 'Date de mise en service': new Date('2022-09-05'), }, components: [ { name: 'Tête compact Z320', reference: 'BE-TETE-320', typeCode: 'bucket-head-section', requirementLabel: "Tête d'élévateur", modelCode: 'bucket-head-95', constructeur: 'agritech', customValues: { 'Largeur tambour (mm)': 680, 'Type de revêtement': 'Céramique', 'Nombre de trappes': 2, }, children: [ { name: 'Motorisation 55 kW', reference: 'MTR-55-EL2', typeCode: 'motor-drive', requirementLabel: 'Motorisation principale', modelCode: 'motor-drive-55', constructeur: 'sew', customValues: { 'Puissance nominale (kW)': 55, 'Classe énergétique': 'IE3', "Indice de protection": 'IP55', }, }, { name: 'Réducteur Bonfiglioli', reference: 'GBX-BF-02', typeCode: 'gearbox-assembly', requirementLabel: 'Réducteur principal', modelCode: 'gearbox-bonfiglioli', constructeur: 'bonfiglioli', customValues: { 'Rapport de réduction': '1:24', 'Couple nominal (Nm)': 2100, 'Type de montage': 'Sur arbre', }, }, ], }, { name: 'Pied élévateur compact', reference: 'BE-PIED-320', typeCode: 'bucket-boot-section', requirementLabel: "Pied d'élévateur", modelCode: 'bucket-boot-compact', constructeur: 'agritech', customValues: { 'Capacité trémie (L)': 360, 'Mode de tension': 'Hydraulique', 'Système de nettoyage': 'Vide-pied', }, }, { name: 'Gaine intermédiaire 2,5 m', reference: 'BE-GAINE-3', typeCode: 'bucket-leg-section', requirementLabel: 'Tronçons de gaine', modelCode: 'bucket-leg-2-5m', constructeur: 'agritech', customValues: { 'Hauteur section (m)': 2.5, 'Type de gaine': 'Boulonnée', }, }, { name: 'Gaine renfort 3 m', reference: 'BE-GAINE-4', typeCode: 'bucket-leg-section', requirementLabel: 'Tronçons de gaine', modelCode: 'bucket-leg-3m', constructeur: 'agritech', customValues: { 'Hauteur section (m)': 3, 'Type de gaine': 'Renforcée', }, }, { name: 'Coffret local aval', reference: 'ARM-EL-02', typeCode: 'control-panel', requirementLabel: 'Armoire locale', modelCode: 'control-panel-s7', constructeur: 'buhler', customValues: { 'Automate principal': 'Siemens S7-1500', 'Année de mise à jour': 2022, "Indice de protection": 'IP65', }, }, ], sparePieces: [ { name: 'Courroie de secours 650 mm', reference: 'SP-BELT-650', typeCode: 'drive-belt', modelCode: 'belt-hd-650', requirementLabel: 'Courroie élévatrice', customValues: { 'Largeur (mm)': 650, Matériau: 'Polyuréthane', }, }, { name: 'Capteur vitesse compact', reference: 'SP-SPEED-02', typeCode: 'speed-sensor', modelCode: 'sensor-speed-m18', constructeur: 'ifm', requirementLabel: 'Capteur de vitesse', customValues: { 'Type de sortie': 'PNP Tout ou rien', 'Plage de mesure (rpm)': 900, }, }, { name: 'Kit visserie élévateur aval', reference: 'SP-VISS-EL2', typeCode: 'hex-screw', modelCode: 'screw-m10x60', requirementLabel: 'Kit visserie structure', customValues: { 'Diamètre (mm)': 10, 'Longueur (mm)': 60, 'Classe acier': '10.9', }, }, ], }, { code: 'belt-conveyor-feed', typeMachineCode: 'belt-conveyor', name: "Convoyeur alimentation 18 m", reference: 'CV-ALIM-18', prix: '32600', constructeurKey: 'valmont', customFieldValues: { 'Débit (t/h)': 110, 'Longueur (m)': 18, Localisation: 'Réception', }, components: [ { name: "Station d'entraînement 800", reference: 'CV-DRIVE-18', typeCode: 'belt-drive-station', requirementLabel: "Station d'entraînement", modelCode: 'belt-drive-800', constructeur: 'valmont', customValues: { 'Type de tambour': 'Caoutchouc rainuré', 'Système de tension': 'Hydraulique', }, children: [ { name: 'Moteur 45 kW', reference: 'MTR-45-CV1', typeCode: 'motor-drive', requirementLabel: 'Motorisation convoyeur', modelCode: 'motor-drive-45', constructeur: 'sew', customValues: { 'Puissance nominale (kW)': 45, 'Classe énergétique': 'IE3', "Indice de protection": 'IP55', }, }, { name: 'Réducteur Bonfiglioli TA', reference: 'GBX-TA-CV1', typeCode: 'gearbox-assembly', requirementLabel: 'Réducteur convoyeur', modelCode: 'gearbox-bonfiglioli', constructeur: 'bonfiglioli', customValues: { 'Rapport de réduction': '1:24', 'Couple nominal (Nm)': 2100, 'Type de montage': 'Sur arbre', }, }, ], }, { name: 'Station de retour 800', reference: 'CV-TAIL-18', typeCode: 'belt-tail-station', requirementLabel: 'Station de retour', modelCode: 'belt-tail-800', constructeur: 'valmont', customValues: { 'Nettoyeur principal': 'Racleur PU', 'Diamètre tambour (mm)': 420, }, pieces: [ { name: 'Grattoir principal PU', reference: 'GRAT-800-01', typeCode: 'flat-gasket', modelCode: 'gasket-ht-200', customValues: { Matière: 'NBR', 'Épaisseur (mm)': 5, }, }, ], }, { name: 'Ossature 18 m', reference: 'CV-FRAME-18', typeCode: 'belt-support-frame', requirementLabel: 'Ossature intermédiaire', modelCode: 'belt-frame-18m', constructeur: 'valmont', customValues: { 'Longueur (m)': 18, 'Nombre de rouleaux': 36, 'Type de châssis': 'Treillis', }, pieces: [ { name: 'Roulement UCP210', reference: 'BRG-UCP210-02', typeCode: 'roller-bearing', modelCode: 'bearing-ucp210', constructeur: 'skf', customValues: { Série: 'UCP', "Type d'étanchéité": '2RS', }, }, ], }, { name: 'Coffret convoyeur réception', reference: 'ARM-CV-01', typeCode: 'control-panel', requirementLabel: 'Coffret de commande', modelCode: 'control-panel-m340', constructeur: 'buhler', customValues: { 'Automate principal': 'Schneider Modicon M340', "Indice de protection": 'IP55', }, }, ], sparePieces: [ { name: 'Bande transporteuse 800 mm', reference: 'SP-BAND-800', typeCode: 'drive-belt', modelCode: 'belt-hd-800', requirementLabel: 'Bande transporteuse', customValues: { 'Largeur (mm)': 800, Matériau: 'Caoutchouc nitrile', }, }, { name: 'Kit palier de rechange', reference: 'SP-BRG-800', typeCode: 'roller-bearing', modelCode: 'bearing-ucp210', requirementLabel: 'Paliers supports', constructeur: 'skf', customValues: { Série: 'UCP', "Type d'étanchéité": '2RS', }, }, { name: 'Visserie ossature', reference: 'SP-VISS-CV1', typeCode: 'hex-screw', modelCode: 'screw-m10x60', requirementLabel: 'Visserie ossature', customValues: { 'Diamètre (mm)': 10, 'Longueur (mm)': 60, 'Classe acier': '10.9', }, }, ], }, { code: 'belt-conveyor-expedition', typeMachineCode: 'belt-conveyor', name: 'Convoyeur expédition 25 m', reference: 'CV-EXP-25', prix: '35400', constructeurKey: 'valmont', customFieldValues: { 'Débit (t/h)': 90, 'Longueur (m)': 25, Localisation: 'Expédition', }, components: [ { name: 'Station tête 650', reference: 'CV-DRIVE-25', typeCode: 'belt-drive-station', requirementLabel: "Station d'entraînement", modelCode: 'belt-drive-650', constructeur: 'valmont', customValues: { 'Type de tambour': 'Céramique', 'Système de tension': 'Vis manuelle', }, children: [ { name: 'Moteur 37 kW', reference: 'MTR-37-CV2', typeCode: 'motor-drive', requirementLabel: 'Motorisation convoyeur', modelCode: 'motor-drive-37', constructeur: 'sew', customValues: { 'Puissance nominale (kW)': 37, 'Classe énergétique': 'IE3', "Indice de protection": 'IP55', }, }, { name: 'Réducteur SEW K', reference: 'GBX-SEW-CV2', typeCode: 'gearbox-assembly', requirementLabel: 'Réducteur convoyeur', modelCode: 'gearbox-sew', constructeur: 'sew', customValues: { 'Rapport de réduction': '1:18', 'Couple nominal (Nm)': 1800, 'Type de montage': 'À pattes', }, }, ], }, { name: 'Station retour 650', reference: 'CV-TAIL-25', typeCode: 'belt-tail-station', requirementLabel: 'Station de retour', modelCode: 'belt-tail-650', constructeur: 'valmont', customValues: { 'Nettoyeur principal': 'Brosse acier', 'Diamètre tambour (mm)': 360, }, }, { name: 'Ossature 25 m', reference: 'CV-FRAME-25', typeCode: 'belt-support-frame', requirementLabel: 'Ossature intermédiaire', modelCode: 'belt-frame-25m', constructeur: 'valmont', customValues: { 'Longueur (m)': 25, 'Nombre de rouleaux': 48, 'Type de châssis': 'Portique', }, }, { name: 'Coffret expédition', reference: 'ARM-CV-02', typeCode: 'control-panel', requirementLabel: 'Coffret de commande', modelCode: 'control-panel-s7', constructeur: 'buhler', customValues: { 'Automate principal': 'Siemens S7-1500', 'Année de mise à jour': 2021, "Indice de protection": 'IP65', }, }, ], sparePieces: [ { name: 'Bande transporteuse 650 mm', reference: 'SP-BAND-650', typeCode: 'drive-belt', modelCode: 'belt-hd-650', requirementLabel: 'Bande transporteuse', customValues: { 'Largeur (mm)': 650, Matériau: 'Polyuréthane', }, }, { name: 'Palier UCFL207', reference: 'SP-BRG-UCFL', typeCode: 'roller-bearing', modelCode: 'bearing-ucfl207', requirementLabel: 'Paliers supports', constructeur: 'skf', customValues: { Série: 'UCFL', "Type d'étanchéité": 'ZZ', }, }, { name: 'Visserie tendeurs', reference: 'SP-VISS-CV2', typeCode: 'hex-screw', modelCode: 'screw-m8x30', requirementLabel: 'Visserie ossature', customValues: { 'Diamètre (mm)': 8, 'Longueur (mm)': 30, 'Classe acier': '8.8', }, }, ], }, { code: 'gravity-table-main', typeMachineCode: 'gravity-separator', name: 'Table densimétrique TQX', reference: 'TBL-TQX-01', prix: '68500', constructeurKey: 'buhler', customFieldValues: { 'Capacité de tri (t/h)': 120, 'Produit traité': 'Blé', 'Date de mise en service': new Date('2021-03-22'), }, components: [ { name: 'Plateau TQX-120', reference: 'TBL-PLT-01', typeCode: 'gravity-vibration-deck', requirementLabel: 'Plateau vibrant', modelCode: 'gravity-deck-120', constructeur: 'buhler', customValues: { 'Type de plateau': 'Acier perforé', 'Fréquence de vibration (Hz)': 45, 'Inclinaison plateau (°)': 5, }, children: [ { name: 'Moteur vibrateur 18,5 kW', reference: 'MTR-18-VIB', typeCode: 'motor-drive', modelCode: 'motor-drive-18', constructeur: 'sew', customValues: { 'Puissance nominale (kW)': 18.5, 'Classe énergétique': 'IE3', "Indice de protection": 'IP55', }, }, ], }, { name: 'Ventilateur aspiration 45 kW', reference: 'VENT-45-01', typeCode: 'ventilation-fan', requirementLabel: 'Ventilateur aspiration', modelCode: 'fan-process-45', constructeur: 'agrifan', customValues: { 'Débit (m³/h)': 45000, 'Type de roue': 'Centrifuge', 'Vitesse nominale (rpm)': 1450, }, }, { name: 'Armoire réglage table', reference: 'ARM-TBL-01', typeCode: 'control-panel', requirementLabel: 'Armoire de réglage', modelCode: 'control-panel-m340', constructeur: 'buhler', customValues: { 'Automate principal': 'Schneider Modicon M340', 'Année de mise à jour': 2023, "Indice de protection": 'IP55', }, }, ], sparePieces: [ { name: 'Capteur vibration M12', reference: 'SP-SNS-VIB', typeCode: 'speed-sensor', modelCode: 'sensor-speed-m12', requirementLabel: 'Capteur vibration', customValues: { 'Type de sortie': 'PNP 4-20 mA', 'Plage de mesure (rpm)': 1500, }, }, { name: 'Kit visserie plateau', reference: 'SP-VISS-TBL', typeCode: 'hex-screw', modelCode: 'screw-m8x30', requirementLabel: 'Kit visserie plateau', customValues: { 'Diamètre (mm)': 8, 'Longueur (mm)': 30, 'Classe acier': '8.8', }, }, { name: 'Cartouche aspiration 610', reference: 'SP-FILT-610', typeCode: 'filter-cartridge', modelCode: 'filter-dust-610', requirementLabel: 'Cartouche aspiration', customValues: { 'Longueur (mm)': 610, 'Média filtrant': 'Polyester', }, }, ], }, { code: 'grain-dryer-main', typeMachineCode: 'grain-dryer', name: 'Séchoir continu SC-60', reference: 'DRY-SC60', prix: '212000', constructeurKey: 'agridry', customFieldValues: { 'Capacité sèche (t/h)': 60, 'Mode d’alimentation': 'Élévateur principal', 'Date de mise en service': new Date('2020-07-15'), }, components: [ { name: 'Brûleur gaz 3 MW', reference: 'BRN-3MW-01', typeCode: 'burner-module', requirementLabel: 'Module brûleur', modelCode: 'burner-module-3mw', constructeur: 'agridry', customValues: { 'Puissance thermique (kW)': 3000, 'Type de carburant': 'Gaz naturel', "Système d'allumage": 'Double électrode', }, }, { name: 'Colonne zone chaude', reference: 'COL-CHAUD-01', typeCode: 'dryer-column-segment', requirementLabel: 'Colonnes de séchage', modelCode: 'dryer-column-2m', constructeur: 'agridry', customValues: { 'Hauteur segment (m)': 2, 'Zone de séchage': 'Échauffage', 'Capteurs intégrés': true, }, }, { name: 'Colonne zone tempérée', reference: 'COL-TEMP-01', typeCode: 'dryer-column-segment', requirementLabel: 'Colonnes de séchage', modelCode: 'dryer-column-1-5m', constructeur: 'agridry', customValues: { 'Hauteur segment (m)': 1.5, 'Zone de séchage': 'Tempe', 'Capteurs intégrés': true, }, }, { name: 'Ventilateur process principal', reference: 'VENT-45-DRY', typeCode: 'ventilation-fan', requirementLabel: 'Ventilation process', modelCode: 'fan-process-45', constructeur: 'agrifan', customValues: { 'Débit (m³/h)': 52000, 'Type de roue': 'Centrifuge', 'Vitesse nominale (rpm)': 1480, }, children: [ { name: 'Motorisation ventilateur 110 kW', reference: 'MTR-110-VENT', typeCode: 'motor-drive', modelCode: 'motor-drive-110', constructeur: 'sew', customValues: { 'Puissance nominale (kW)': 110, 'Classe énergétique': 'IE3', "Indice de protection": 'IP55', }, }, ], }, { name: 'Filtre cyclone 610', reference: 'FIL-CYCL-01', typeCode: 'dust-filter', requirementLabel: 'Filtre poussières', modelCode: 'dust-filter-cyclone', constructeur: 'agrifan', customValues: { 'Efficacité de filtration (%)': 98, 'Type de média filtrant': 'Polyester', 'Nombre de cartouches': 6, }, pieces: [ { name: 'Cartouche polyester 610', reference: 'FILT-610-01', typeCode: 'filter-cartridge', modelCode: 'filter-dust-610', customValues: { 'Longueur (mm)': 610, 'Média filtrant': 'Polyester', }, }, ], }, { name: 'Armoire pilotage séchoir', reference: 'ARM-DRY-01', typeCode: 'control-panel', requirementLabel: 'Armoire de pilotage', modelCode: 'control-panel-m340', constructeur: 'buhler', customValues: { 'Automate principal': 'Schneider Modicon M340', 'Année de mise à jour': 2024, "Indice de protection": 'IP55', }, }, ], sparePieces: [ { name: 'Sonde PT100 longue', reference: 'SP-PT100-01', typeCode: 'temperature-probe', modelCode: 'temp-probe-pt100', requirementLabel: 'Sondes température', customValues: { Type: 'PT100 classe A', 'Longueur tige (mm)': 300, }, }, { name: 'Sonde PT100 courte', reference: 'SP-PT100-02', typeCode: 'temperature-probe', modelCode: 'temp-probe-pt100-short', requirementLabel: 'Sondes température', customValues: { Type: 'PT100 classe B', 'Longueur tige (mm)': 200, }, }, { name: 'Joint trappe brûleur', reference: 'SP-JOINT-DRY', typeCode: 'flat-gasket', modelCode: 'gasket-ht-200', requirementLabel: 'Joints haute température', customValues: { Matière: 'Fibre compressée', 'Épaisseur (mm)': 4, }, }, { name: 'Cartouche rechange 480', reference: 'SP-FILT-480', typeCode: 'filter-cartridge', modelCode: 'filter-dust-480', requirementLabel: 'Cartouches dépoussiéreur', customValues: { 'Longueur (mm)': 480, 'Média filtrant': 'Polyester', }, }, ], }, { code: 'screw-conveyor-north', typeMachineCode: 'screw-conveyor', name: 'Vis de reprise nord V200', reference: 'SC-V200-N', prix: '27400', constructeurKey: 'valmont', customFieldValues: { 'Diamètre vis (mm)': 200, 'Inclinaison (°)': 12, 'Vitesse (rpm)': 140, }, components: [ { name: 'Caisson principal 200', reference: 'SC-CAISSON-200', typeCode: 'screw-trough-section', requirementLabel: 'Caisson principal', modelCode: 'screw-trough-200', constructeur: 'valmont', customValues: { 'Longueur (m)': 9, 'Diamètre vis (mm)': 200, Matériau: 'Acier peint', }, }, { name: "Trémie d'alimentation 200", reference: 'SC-TREMIE-200', typeCode: 'screw-inlet-hopper', requirementLabel: "Trémie d'alimentation", modelCode: 'screw-inlet-200', constructeur: 'valmont', customValues: { 'Capacité (L)': 220, 'Type de grille': 'Grille anti-gravats', }, }, { name: 'Goulotte sortie vanne', reference: 'SC-GOUL-200', typeCode: 'screw-outlet-chute', requirementLabel: 'Goulotte de sortie', modelCode: 'screw-outlet-vanne', constructeur: 'valmont', customValues: { 'Type de vanne': 'Guillotine', "Orientation (°)": 45, }, }, { name: 'Moteur vis 18.5 kW', reference: 'MTR-18-SC1', typeCode: 'motor-drive', requirementLabel: 'Motorisation vis', modelCode: 'motor-drive-18', constructeur: 'sew', customValues: { 'Puissance nominale (kW)': 18.5, 'Classe énergétique': 'IE3', "Indice de protection": 'IP55', }, }, { name: 'Réducteur SEW K', reference: 'GBX-SEW-SC1', typeCode: 'gearbox-assembly', requirementLabel: 'Réducteur vis', modelCode: 'gearbox-sew', constructeur: 'sew', customValues: { 'Rapport de réduction': '1:32', 'Couple nominal (Nm)': 1800, 'Type de montage': 'À pattes', }, }, ], sparePieces: [ { name: 'Palier UCP210', reference: 'SP-PALIER-200', typeCode: 'roller-bearing', modelCode: 'bearing-ucp210', requirementLabel: 'Paliers de ligne', constructeur: 'skf', customValues: { Série: 'UCP', "Type d'étanchéité": '2RS', }, }, { name: 'Kit visserie caisson', reference: 'SP-VISS-SC1', typeCode: 'hex-screw', modelCode: 'screw-m12x80', requirementLabel: 'Kit visserie caisson', customValues: { 'Diamètre (mm)': 12, 'Longueur (mm)': 80, 'Classe acier': '8.8', }, }, { name: 'Cartouche graisse 400g', reference: 'SP-GRAISSE-01', typeCode: 'lubrication-cartridge', modelCode: 'grease-cartridge-400', requirementLabel: 'Cartouches de graisse', customValues: { 'Volume (cm³)': 400, 'Grade de graisse': 'NLGI 2', }, }, ], }, { code: 'screw-conveyor-south', typeMachineCode: 'screw-conveyor', name: 'Vis de reprise sud V160', reference: 'SC-V160-S', prix: '23600', constructeurKey: 'valmont', customFieldValues: { 'Diamètre vis (mm)': 160, 'Inclinaison (°)': 8, 'Vitesse (rpm)': 110, }, components: [ { name: 'Caisson principal 160', reference: 'SC-CAISSON-160', typeCode: 'screw-trough-section', requirementLabel: 'Caisson principal', modelCode: 'screw-trough-160', constructeur: 'valmont', customValues: { 'Longueur (m)': 7, 'Diamètre vis (mm)': 160, Matériau: 'Galvanisé', }, }, { name: "Trémie d'alimentation 160", reference: 'SC-TREMIE-160', typeCode: 'screw-inlet-hopper', requirementLabel: "Trémie d'alimentation", modelCode: 'screw-inlet-160', constructeur: 'valmont', customValues: { 'Capacité (L)': 160, 'Type de grille': 'Grille magnétique', }, }, { name: 'Goulotte clapet', reference: 'SC-GOUL-160', typeCode: 'screw-outlet-chute', requirementLabel: 'Goulotte de sortie', modelCode: 'screw-outlet-flap', constructeur: 'valmont', customValues: { 'Type de vanne': 'By-pass', "Orientation (°)": 60, }, }, { name: 'Moteur vis 15 kW', reference: 'MTR-15-SC2', typeCode: 'motor-drive', requirementLabel: 'Motorisation vis', modelCode: 'motor-drive-15', constructeur: 'sew', customValues: { 'Puissance nominale (kW)': 15, 'Classe énergétique': 'IE3', "Indice de protection": 'IP55', }, }, { name: 'Réducteur Bonfiglioli', reference: 'GBX-BF-SC2', typeCode: 'gearbox-assembly', requirementLabel: 'Réducteur vis', modelCode: 'gearbox-bonfiglioli', constructeur: 'bonfiglioli', customValues: { 'Rapport de réduction': '1:28', 'Couple nominal (Nm)': 1600, 'Type de montage': 'Sur arbre', }, }, ], sparePieces: [ { name: 'Palier UCFL207', reference: 'SP-PALIER-160', typeCode: 'roller-bearing', modelCode: 'bearing-ucfl207', requirementLabel: 'Paliers de ligne', constructeur: 'skf', customValues: { Série: 'UCFL', "Type d'étanchéité": 'ZZ', }, }, { name: 'Kit visserie vis 160', reference: 'SP-VISS-SC2', typeCode: 'hex-screw', modelCode: 'screw-m10x60', requirementLabel: 'Kit visserie caisson', customValues: { 'Diamètre (mm)': 10, 'Longueur (mm)': 60, 'Classe acier': '10.9', }, }, { name: 'Cartouche graisse 400g', reference: 'SP-GRAISSE-02', typeCode: 'lubrication-cartridge', modelCode: 'grease-cartridge-400', requirementLabel: 'Cartouches de graisse', customValues: { 'Volume (cm³)': 400, 'Grade de graisse': 'NLGI 2', }, }, ], }, { code: 'weigh-hopper-truck', typeMachineCode: 'weigh-hopper', name: 'Benne peseuse camion 5T', reference: 'BP-5000-01', prix: '39200', constructeurKey: 'buhler', customFieldValues: { 'Capacité de pesée (kg)': 5000, 'Précision (%)': 0.5, 'Mode de vidange': 'Trappe motorisée', }, components: [ { name: 'Cadre peseur 5T', reference: 'BP-CADRE-01', typeCode: 'weigh-load-frame', requirementLabel: 'Cadre peseur', modelCode: 'weigh-frame-5t', constructeur: 'buhler', customValues: { 'Capacité nominale (kg)': 5000, 'Nombre de capteurs': 4, 'Protection IP': 'IP65', }, }, { name: 'Vanne hydraulique rapide', reference: 'BP-VANNE-01', typeCode: 'weigh-discharge-gate', requirementLabel: 'Vanne de vidange', modelCode: 'weigh-gate-hydraulic', constructeur: 'poclain', customValues: { "Type d'actionneur": 'Hydraulique', "Temps d'ouverture (s)": 4, }, }, { name: 'Coffret pesage camion', reference: 'ARM-BP-01', typeCode: 'control-panel', requirementLabel: 'Coffret de pesage', modelCode: 'control-panel-m340', constructeur: 'buhler', customValues: { 'Automate principal': 'Schneider Modicon M340', 'Année de mise à jour': 2023, "Indice de protection": 'IP55', }, }, ], sparePieces: [ { name: 'Capteur pesage 5T', reference: 'SP-LC-5T-01', typeCode: 'load-cell', modelCode: 'load-cell-5t', requirementLabel: 'Capteurs de pesage', constructeur: 'ifm', customValues: { 'Capacité (kg)': 5000, 'Type de connexion': 'Câble 6 fils', }, }, { name: 'Capteur pesage secours', reference: 'SP-LC-5T-02', typeCode: 'load-cell', modelCode: 'load-cell-5t', requirementLabel: 'Capteurs de pesage', constructeur: 'ifm', customValues: { 'Capacité (kg)': 5000, 'Type de connexion': 'Câble 6 fils', }, }, { name: 'Fusibles 40A coffret', reference: 'SP-FS-40A-01', typeCode: 'fuse-cartridge', modelCode: 'fuse-gg-40a', requirementLabel: 'Fusibles de protection', customValues: { 'Calibre (A)': 40, Type: 'gG', }, }, { name: 'Joint trappe benne', reference: 'SP-JNT-BP', typeCode: 'flat-gasket', modelCode: 'gasket-ht-200', requirementLabel: 'Joint trappe', customValues: { Matière: 'NBR', 'Épaisseur (mm)': 5, }, }, ], }, { code: 'telehandler-mlt841', typeMachineCode: 'telehandler', name: 'Manitou MLT 841 Logistique', reference: 'MLT-841-01', prix: '87500', constructeurKey: 'manitou', customFieldValues: { 'Usage principal': 'Chargement camions', 'Lieu de stationnement': 'Hangar nord', "Année d'achat": 2021, }, components: [ { name: 'Flèche télescopique 8 m', reference: 'MLT-BOOM-01', typeCode: 'telehandler-boom', requirementLabel: 'Flèche télescopique', modelCode: 'tele-boom-8m', constructeur: 'manitou', customValues: { 'Hauteur max (m)': 8, 'Sections télescopiques': 4, 'Type de guidage': 'Galets', }, }, { name: 'Groupe hydraulique 140 l/min', reference: 'MLT-HYDRO-01', typeCode: 'hydraulic-power-pack', requirementLabel: 'Groupe hydraulique', modelCode: 'hydraulic-pack-tele', constructeur: 'poclain', customValues: { 'Débit nominal (l/min)': 140, 'Pression max (bar)': 280, 'Type de pompe': 'Piston axial', }, }, { name: 'Groupe moteur 110 kW', reference: 'MLT-MOTEUR-01', typeCode: 'motor-drive', requirementLabel: 'Groupe moteur', modelCode: 'motor-drive-110', constructeur: 'sew', customValues: { 'Puissance nominale (kW)': 110, 'Classe énergétique': 'IE3', "Indice de protection": 'IP55', }, }, { name: 'Cabine premium climatisée', reference: 'MLT-CAB-01', typeCode: 'telehandler-cab-module', requirementLabel: 'Cabine opérateur', modelCode: 'tele-cab-premium', constructeur: 'manitou', customValues: { 'Type de cabine': 'Premium climatisée', Climatisation: true, 'Nombre de caméras': 2, }, }, { name: 'Support attache rapide', reference: 'MLT-ATTACHE-01', typeCode: 'telehandler-attachment-carrier', requirementLabel: 'Support d’outils', modelCode: 'tele-carrier-quick', constructeur: 'manitou', customValues: { "Type d'attache": 'Attache Manitou', 'Capacité nominale (t)': 4.1, }, }, ], sparePieces: [ { name: 'Flexible hydraulique 2 tresses', reference: 'SP-HOSE-01', typeCode: 'hydraulic-hose', modelCode: 'hydraulic-hose-2w', requirementLabel: 'Flexibles hydrauliques', constructeur: 'poclain', customValues: { 'Pression max (bar)': 420, 'Type de renfort': '2 tresses acier', 'Longueur (mm)': 1800, }, }, { name: 'Fusibles cabine 40A', reference: 'SP-FS-CAB', typeCode: 'fuse-cartridge', modelCode: 'fuse-gg-40a', requirementLabel: 'Fusibles cabine', customValues: { 'Calibre (A)': 40, Type: 'gG', }, }, { name: 'Cartouche graisse MLT', reference: 'SP-GRAISSE-MLT', typeCode: 'lubrication-cartridge', modelCode: 'grease-cartridge-400', requirementLabel: 'Cartouches graissage', customValues: { 'Volume (cm³)': 400, 'Grade de graisse': 'NLGI 2', }, }, ], }, ]; 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; } function mapCustomFields(fields: { id: string; name: string }[]) { return fields.reduce>((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 }, ][] = []; 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 }, ][] = []; for (const definition of pieceTypeDefinitions) { const record = await prisma.modelType.create({ data: { name: definition.name, code: definition.code, category: ModelCategory.PIECE, 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 }, }); pieceTypeEntries.push([ definition.code, { id: record.id, customFields: mapCustomFields(record.customFields) }, ]); } return { componentTypes: Object.fromEntries(componentTypeEntries) as Record< string, { id: string; customFields: Record } >, pieceTypes: Object.fromEntries(pieceTypeEntries) as Record< string, { id: string; customFields: Record } >, }; } async function createPieceModels( pieceTypes: Record, ) { console.log('🧩 Création des modèles de pièces...'); const entries = await Promise.all( pieceModelDefinitions.map(async (definition) => { const type = pieceTypes[definition.typeCode]; if (!type) { throw new Error(`Type de pièce introuvable: ${definition.typeCode}`); } const record = await prisma.pieceModel.create({ data: { name: definition.name, description: definition.description, typePiece: { connect: { id: type.id } }, structure: definition.structure, }, }); return [definition.code, record] as const; }), ); return Object.fromEntries(entries) as Record; } async function createComponentModels( componentTypes: Record, ) { console.log('🛠️ Création des modèles de composants...'); const entries = await Promise.all( componentModelDefinitions.map(async (definition) => { const type = componentTypes[definition.typeCode]; if (!type) { throw new Error(`Type de composant introuvable: ${definition.typeCode}`); } const record = await prisma.composantModel.create({ data: { name: definition.name, description: definition.description, typeComposant: { connect: { id: type.id } }, structure: definition.structure, }, }); return [definition.code, record] as const; }), ); return Object.fromEntries(entries) as Record; } async function createTypeMachines( componentTypes: Record, pieceTypes: Record, ) { console.log('🧬 Création des squelettes de machines...'); const entries = await Promise.all( typeMachineDefinitions.map(async (definition) => { const record = await prisma.typeMachine.create({ data: { name: definition.name, description: definition.description, category: definition.category, maintenanceFrequency: definition.maintenanceFrequency, specifications: definition.specifications, components: { layout: definition.componentRequirements.map((requirement, index) => ({ order: index + 1, zone: requirement.label, type: requirement.typeCode, })), }, machinePieces: { recommendedStock: [], }, customFields: { create: definition.customFields.map((field) => ({ name: field.name, type: field.type, required: field.required ?? false, defaultValue: field.defaultValue, options: field.options ?? [], })), }, componentRequirements: { create: definition.componentRequirements.map((requirement) => ({ label: requirement.label, minCount: requirement.minCount, maxCount: requirement.maxCount, required: requirement.required, typeComposant: { connect: { id: componentTypes[requirement.typeCode].id }, }, })), }, pieceRequirements: definition.pieceRequirements ? { create: definition.pieceRequirements.map((requirement) => ({ label: requirement.label, minCount: requirement.minCount, maxCount: requirement.maxCount, required: requirement.required, typePiece: { connect: { id: pieceTypes[requirement.typeCode].id }, }, })), } : undefined, }, include: { customFields: true, componentRequirements: true, pieceRequirements: true, }, }); return [definition.code, record] as const; }), ); return Object.fromEntries(entries) as Record; } function buildCustomFieldValues( fieldMap: Record, values?: Record, ) { 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 }>; componentModels: Record; pieceTypes: Record }>; pieceModels: Record; constructeurs: Record; requirementMap: Map; }, 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 }, }, constructeur: component.constructeur ? { connect: { id: context.constructeurs[component.constructeur].id } } : undefined, typeMachineComponentRequirement: requirementId ? { connect: { id: requirementId } } : 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 createMachines( siteId: string, typeMachines: Record, context: { componentTypes: Record }>; componentModels: Record; pieceTypes: Record }>; pieceModels: Record; constructeurs: Record; }, ) { console.log('🏗️ Création des machines de démonstration...'); for (const build of machineBuilds) { const typeMachine = typeMachines[build.typeMachineCode]; if (!typeMachine) { throw new Error(`Type de machine introuvable pour ${build.typeMachineCode}`); } const requirementMap = new Map(); typeMachine.componentRequirements.forEach((requirement) => { if (requirement.label) { requirementMap.set(requirement.label, requirement.id); } }); const pieceRequirementMap = new Map(); 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: build.name, reference: build.reference, prix: new Prisma.Decimal(build.prix), site: { connect: { id: siteId } }, typeMachine: { connect: { id: typeMachine.id } }, constructeur: { connect: { id: context.constructeurs[build.constructeurKey].id }, }, customFieldValues: buildCustomFieldValues( machineCustomFieldMap, build.customFieldValues, ), }, }); console.log(`⚙️ ${build.name} - ajout des composants...`); const componentContext = { ...context, requirementMap, }; for (const component of build.components) { await createComponentHierarchy(machine.id, component, componentContext); } if (build.sparePieces && build.sparePieces.length > 0) { console.log(`📦 ${build.name} - enregistrement des pièces de réserve...`); for (const spare of build.sparePieces) { const pieceType = context.pieceTypes[spare.typeCode]; if (!pieceType) { throw new Error(`Type de pièce inconnu pour pièce de secours: ${spare.typeCode}`); } const requirementId = spare.requirementLabel ? pieceRequirementMap.get(spare.requirementLabel) : undefined; await prisma.piece.create({ data: { name: spare.name, reference: spare.reference, prix: spare.prix ? new Prisma.Decimal(spare.prix) : undefined, machine: { connect: { id: machine.id } }, typePiece: { connect: { id: pieceType.id } }, pieceModel: { connect: { id: context.pieceModels[spare.modelCode].id } }, constructeur: spare.constructeur ? { connect: { id: context.constructeurs[spare.constructeur].id } } : undefined, typeMachinePieceRequirement: requirementId ? { connect: { id: requirementId } } : undefined, customFieldValues: buildCustomFieldValues( pieceType.customFields, spare.customValues, ), }, }); } } } } async function main() { try { await clearDatabaseExceptSitesAndProfiles(); const [site, constructeurs] = await Promise.all([ ensureDemoSite(), createConstructeurs(), ]); const { componentTypes, pieceTypes } = await createModelTypes(); const [pieceModels, componentModels, typeMachines] = await Promise.all([ createPieceModels(pieceTypes), createComponentModels(componentTypes), createTypeMachines(componentTypes, pieceTypes), ]); await createMachines(site.id, typeMachines, { 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();