Normalize component model structures in industrial seed
This commit is contained in:
@@ -1,4 +1,6 @@
|
|||||||
import { PrismaClient, Prisma, ModelCategory } from '@prisma/client';
|
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();
|
const prisma = new PrismaClient();
|
||||||
|
|
||||||
@@ -32,12 +34,33 @@ type PieceModelDefinition = {
|
|||||||
structure?: Prisma.InputJsonValue;
|
structure?: Prisma.InputJsonValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type ComponentModelStructureDraft =
|
||||||
|
| ComponentModelStructure
|
||||||
|
| ({
|
||||||
|
recommendedCustomFields?: Record<string, unknown>;
|
||||||
|
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<string, unknown>);
|
||||||
|
|
||||||
type ComponentModelDefinition = {
|
type ComponentModelDefinition = {
|
||||||
code: string;
|
code: string;
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
typeCode: string;
|
typeCode: string;
|
||||||
structure?: Prisma.InputJsonValue;
|
structure?: ComponentModelStructureDraft | Prisma.InputJsonValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ConstructeurDefinition = {
|
type ConstructeurDefinition = {
|
||||||
@@ -4207,8 +4230,164 @@ async function createPieceModels(
|
|||||||
return Object.fromEntries(entries) as Record<string, { id: string }>;
|
return Object.fromEntries(entries) as Record<string, { id: string }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildComponentModelStructure(
|
||||||
|
structure: ComponentModelStructureDraft | Prisma.InputJsonValue | undefined,
|
||||||
|
componentTypes: Record<string, { id: string }>,
|
||||||
|
pieceTypes: Record<string, { id: string }>,
|
||||||
|
): Prisma.InputJsonValue | undefined {
|
||||||
|
if (!structure) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof structure !== 'object' || structure === null) {
|
||||||
|
return structure as Prisma.InputJsonValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const candidate = structure as Record<string, unknown>;
|
||||||
|
|
||||||
|
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<string, unknown>();
|
||||||
|
|
||||||
|
const presetCustomFields = Array.isArray((candidate as any).customFields)
|
||||||
|
? ((candidate as any).customFields as Array<Record<string, unknown>>)
|
||||||
|
: [];
|
||||||
|
|
||||||
|
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<string, unknown>
|
||||||
|
| 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<Record<string, unknown>>)
|
||||||
|
: [];
|
||||||
|
|
||||||
|
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<Record<string, unknown>>)
|
||||||
|
: [];
|
||||||
|
|
||||||
|
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(
|
async function createComponentModels(
|
||||||
componentTypes: Record<string, { id: string }>,
|
componentTypes: Record<string, { id: string }>,
|
||||||
|
pieceTypes: Record<string, { id: string }>,
|
||||||
) {
|
) {
|
||||||
console.log('🛠️ Création des modèles de composants...');
|
console.log('🛠️ Création des modèles de composants...');
|
||||||
|
|
||||||
@@ -4224,7 +4403,11 @@ async function createComponentModels(
|
|||||||
name: definition.name,
|
name: definition.name,
|
||||||
description: definition.description,
|
description: definition.description,
|
||||||
typeComposant: { connect: { id: type.id } },
|
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 { componentTypes, pieceTypes } = await createModelTypes();
|
||||||
const [pieceModels, componentModels, typeMachines] = await Promise.all([
|
const [pieceModels, componentModels, typeMachines] = await Promise.all([
|
||||||
createPieceModels(pieceTypes),
|
createPieceModels(pieceTypes),
|
||||||
createComponentModels(componentTypes),
|
createComponentModels(componentTypes, pieceTypes),
|
||||||
createTypeMachines(componentTypes, pieceTypes),
|
createTypeMachines(componentTypes, pieceTypes),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user