diff --git a/scripts/seed-industrial-data.ts b/scripts/seed-industrial-data.ts index a0b12fe..31df185 100644 --- a/scripts/seed-industrial-data.ts +++ b/scripts/seed-industrial-data.ts @@ -1,4 +1,6 @@ import { PrismaClient, Prisma, ModelCategory } from '@prisma/client'; +import { normalizeComponentModelStructure } from '../src/component-models/structure.normalizer'; +import type { ComponentModelStructure } from '../src/shared/types/inventory'; const prisma = new PrismaClient(); @@ -32,12 +34,33 @@ type PieceModelDefinition = { structure?: Prisma.InputJsonValue; }; +type ComponentModelStructureDraft = + | ComponentModelStructure + | ({ + recommendedCustomFields?: Record; + customFields?: Array<{ key?: string; name?: string; value?: unknown }>; + pieceTemplates?: Array<{ + typeCode?: string; + modelCode?: string; + quantity?: number; + usage?: string; + notes?: string; + role?: string; + }>; + subComponentTemplates?: Array<{ + typeCode?: string; + suggestedModelCodes?: string[]; + alias?: string; + notes?: string; + }>; + } & Record); + type ComponentModelDefinition = { code: string; name: string; description: string; typeCode: string; - structure?: Prisma.InputJsonValue; + structure?: ComponentModelStructureDraft | Prisma.InputJsonValue; }; type ConstructeurDefinition = { @@ -4207,8 +4230,164 @@ async function createPieceModels( return Object.fromEntries(entries) as Record; } +function buildComponentModelStructure( + structure: ComponentModelStructureDraft | Prisma.InputJsonValue | undefined, + componentTypes: Record, + pieceTypes: Record, +): Prisma.InputJsonValue | undefined { + if (!structure) { + return undefined; + } + + if (typeof structure !== 'object' || structure === null) { + return structure as Prisma.InputJsonValue; + } + + const candidate = structure as Record; + + const asCleanString = (value: unknown): string | undefined => { + if (value === undefined || value === null) { + return undefined; + } + const text = String(value).trim().replace(/\s+/g, ' '); + return text ? text : undefined; + }; + + if ( + Array.isArray((candidate as any).pieces) || + Array.isArray((candidate as any).customFields) || + Array.isArray((candidate as any).subcomponents) || + Array.isArray((candidate as any).subComponents) + ) { + return normalizeComponentModelStructure(candidate) as Prisma.InputJsonValue; + } + + const customFieldEntries = new Map(); + + const presetCustomFields = Array.isArray((candidate as any).customFields) + ? ((candidate as any).customFields as Array>) + : []; + + for (const entry of presetCustomFields) { + const key = String(entry?.key ?? entry?.name ?? '').trim(); + if (!key) { + continue; + } + if (!customFieldEntries.has(key)) { + customFieldEntries.set(key, entry?.value ?? null); + } + } + + const recommended = (candidate as any).recommendedCustomFields as + | Record + | undefined; + + if (recommended) { + for (const [key, value] of Object.entries(recommended)) { + const trimmedKey = String(key).trim(); + if (!trimmedKey) { + continue; + } + if (!customFieldEntries.has(trimmedKey)) { + customFieldEntries.set(trimmedKey, value ?? null); + } + } + } + + const pieces: ComponentModelStructure['pieces'] = []; + const subcomponents: ComponentModelStructure['subcomponents'] = []; + + const pieceTemplates = Array.isArray((candidate as any).pieceTemplates) + ? ((candidate as any).pieceTemplates as Array>) + : []; + + for (const template of pieceTemplates) { + const typeCode = String(template?.typeCode ?? '').trim(); + if (!typeCode) { + continue; + } + + const normalizedRole = asCleanString( + template?.usage ?? template?.role ?? template?.notes ?? null, + ); + + if (pieceTypes[typeCode]) { + pieces.push( + normalizedRole + ? { familyCode: typeCode, role: normalizedRole } + : { familyCode: typeCode }, + ); + continue; + } + + if (componentTypes[typeCode]) { + subcomponents.push( + normalizedRole + ? { familyCode: typeCode, alias: normalizedRole } + : { familyCode: typeCode }, + ); + continue; + } + + pieces.push( + normalizedRole + ? { familyCode: typeCode, role: normalizedRole } + : { familyCode: typeCode }, + ); + } + + const subComponentTemplates = Array.isArray((candidate as any).subComponentTemplates) + ? ((candidate as any).subComponentTemplates as Array>) + : []; + + for (const template of subComponentTemplates) { + const typeCode = String(template?.typeCode ?? '').trim(); + const normalizedAlias = asCleanString(template?.alias ?? template?.notes ?? null); + const suggestedModels = Array.isArray(template?.suggestedModelCodes) + ? (template?.suggestedModelCodes as string[]) + : []; + + if (suggestedModels.length > 0) { + suggestedModels.forEach((modelCode, index) => { + const hint = + normalizedAlias && suggestedModels.length > 1 + ? `${normalizedAlias} #${index + 1}` + : normalizedAlias; + const fallbackFamily = typeCode || String(modelCode ?? '').trim() || 'UNKNOWN'; + subcomponents.push( + hint + ? { familyCode: fallbackFamily, alias: hint } + : { familyCode: fallbackFamily }, + ); + }); + continue; + } + + if (typeCode) { + subcomponents.push( + normalizedAlias + ? { familyCode: typeCode, alias: normalizedAlias } + : { familyCode: typeCode }, + ); + continue; + } + } + + const canonical: ComponentModelStructure = { + pieces, + subcomponents, + customFields: Array.from(customFieldEntries.entries()).map(([key, value]) => ({ + key, + value: value ?? null, + })), + }; + + return normalizeComponentModelStructure(canonical) as Prisma.InputJsonValue; +} + async function createComponentModels( componentTypes: Record, + pieceTypes: Record, ) { console.log('🛠️ Création des modèles de composants...'); @@ -4224,7 +4403,11 @@ async function createComponentModels( name: definition.name, description: definition.description, typeComposant: { connect: { id: type.id } }, - structure: definition.structure, + structure: buildComponentModelStructure( + definition.structure, + componentTypes, + pieceTypes, + ), }, }); @@ -4519,7 +4702,7 @@ async function main() { const { componentTypes, pieceTypes } = await createModelTypes(); const [pieceModels, componentModels, typeMachines] = await Promise.all([ createPieceModels(pieceTypes), - createComponentModels(componentTypes), + createComponentModels(componentTypes, pieceTypes), createTypeMachines(componentTypes, pieceTypes), ]);