Migrate away from legacy component and piece models

This commit is contained in:
MatthieuTD
2025-10-02 15:44:02 +02:00
parent 44fd4bb8c7
commit c23ba3a587
34 changed files with 1821 additions and 1825 deletions

View File

@@ -32,10 +32,6 @@ export class CreateComposantDto {
@IsString()
typeMachineComponentRequirementId: string;
@IsOptional()
@IsString()
composantModelId?: string;
}
export class UpdateComposantDto {
@@ -59,8 +55,4 @@ export class UpdateComposantDto {
@IsOptional()
@IsString()
typeComposantId?: string;
@IsOptional()
@IsString()
composantModelId?: string;
}

View File

@@ -8,7 +8,7 @@ export class MachineComponentSelectionDto {
@IsOptional()
@IsString()
componentModelId?: string;
typeComposantId?: string;
@IsOptional()
definition?: any;
@@ -18,8 +18,12 @@ export class MachinePieceSelectionDto {
@IsString()
requirementId: string;
@IsOptional()
@IsString()
pieceModelId: string;
typePieceId?: string;
@IsOptional()
definition?: any;
}
export class CreateMachineDto {

View File

@@ -32,10 +32,6 @@ export class CreatePieceDto {
@IsString()
typeMachinePieceRequirementId: string;
@IsOptional()
@IsString()
pieceModelId?: string;
}
export class UpdatePieceDto {
@@ -59,8 +55,4 @@ export class UpdatePieceDto {
@IsOptional()
@IsString()
typePieceId?: string;
@IsOptional()
@IsString()
pieceModelId?: string;
}

View File

@@ -9,7 +9,10 @@ import {
} from 'class-validator';
import { Type } from 'class-transformer';
import { ValidateNested } from 'class-validator';
import type { ComponentModelStructure } from '../types/inventory';
import type {
ComponentModelStructure,
PieceModelStructure,
} from '../types/inventory';
export enum CustomFieldType {
TEXT = 'text',
@@ -197,6 +200,10 @@ export class CreateTypeComposantDto {
@IsOptional()
@IsArray()
customFields?: CreateCustomFieldDto[];
@IsOptional()
@IsObject()
structure?: ComponentModelStructure;
}
export class UpdateTypeComposantDto {
@@ -211,6 +218,10 @@ export class UpdateTypeComposantDto {
@IsOptional()
@IsArray()
customFields?: CreateCustomFieldDto[];
@IsOptional()
@IsObject()
structure?: ComponentModelStructure;
}
export class CreateTypePieceDto {
@@ -224,6 +235,10 @@ export class CreateTypePieceDto {
@IsOptional()
@IsArray()
customFields?: CreateCustomFieldDto[];
@IsOptional()
@IsObject()
structure?: PieceModelStructure;
}
export class UpdateTypePieceDto {
@@ -238,68 +253,9 @@ export class UpdateTypePieceDto {
@IsOptional()
@IsArray()
customFields?: CreateCustomFieldDto[];
@IsOptional()
@IsObject()
structure?: PieceModelStructure;
}
export class CreateComposantModelDto {
@IsString()
name: string;
@IsOptional()
@IsString()
description?: string;
@IsString()
typeComposantId: string;
@IsOptional()
structure?: ComponentModelStructure;
}
export class UpdateComposantModelDto {
@IsOptional()
@IsString()
name?: string;
@IsOptional()
@IsString()
description?: string;
@IsOptional()
@IsString()
typeComposantId?: string;
@IsOptional()
structure?: ComponentModelStructure;
}
export class CreatePieceModelDto {
@IsString()
name: string;
@IsOptional()
@IsString()
description?: string;
@IsString()
typePieceId: string;
@IsOptional()
structure?: any;
}
export class UpdatePieceModelDto {
@IsOptional()
@IsString()
name?: string;
@IsOptional()
@IsString()
description?: string;
@IsOptional()
@IsString()
typePieceId?: string;
@IsOptional()
structure?: any;
}

View File

@@ -1,5 +1,9 @@
import { normalizeComponentModelStructure } from '../../component-models/structure.normalizer';
import type { ComponentModelStructure } from '../types/inventory';
import type {
ComponentModelStructure,
PieceModelCustomField,
PieceModelStructure,
} from '../types/inventory';
export class ComponentModelStructureValidationError extends Error {
constructor(message: string) {
@@ -150,3 +154,109 @@ export const ComponentModelStructureSchema = {
};
},
};
export class PieceModelStructureValidationError extends Error {
constructor(message: string) {
super(message);
this.name = 'PieceModelStructureValidationError';
}
}
function toStringOrNull(value: unknown): string | null {
if (value === undefined || value === null) {
return null;
}
const trimmed = String(value).trim();
return trimmed ? trimmed : null;
}
function normalizePieceModelCustomFields(
customFields: unknown,
): PieceModelCustomField[] {
if (!Array.isArray(customFields)) {
return [];
}
const normalized: PieceModelCustomField[] = [];
customFields.forEach((entry, index) => {
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
return;
}
const record = entry as Record<string, unknown>;
const rawName =
(typeof record.name === 'string' ? record.name : undefined) ??
(typeof record.key === 'string' ? record.key : undefined) ??
undefined;
const name = rawName ? rawName.trim() : '';
if (!name) {
throw new PieceModelStructureValidationError(
`customFields[${index}].name doit être une chaîne non vide`,
);
}
const field: PieceModelCustomField = { name };
if ('value' in record) {
field.value = record.value;
}
if (typeof record.type === 'string') {
field.type = record.type;
}
if ('required' in record) {
field.required = Boolean(record.required);
}
if (Array.isArray(record.options)) {
field.options = record.options;
} else if (typeof record.optionsText === 'string') {
const options = record.optionsText
.split(/\r?\n/)
.map((option) => option.trim())
.filter((option) => option.length > 0);
if (options.length > 0) {
field.options = options;
}
}
normalized.push(field);
});
return normalized;
}
export const PieceModelStructureSchema = {
parse(input: unknown): PieceModelStructure {
if (input === undefined || input === null) {
return { customFields: [] };
}
if (typeof input !== 'object' || Array.isArray(input)) {
throw new PieceModelStructureValidationError(
'La structure de pièce doit être un objet JSON.',
);
}
const record = input as Record<string, unknown>;
const structure: PieceModelStructure = { ...record };
const customFields = normalizePieceModelCustomFields(record.customFields);
if (customFields.length > 0 || 'customFields' in record) {
structure.customFields = customFields;
}
const normalizedTypePiece = toStringOrNull(record.typePieceId);
if (normalizedTypePiece) {
structure.typePieceId = normalizedTypePiece;
} else if ('typePieceId' in record) {
delete (structure as Record<string, unknown>).typePieceId;
}
return structure;
},
};

View File

@@ -39,3 +39,16 @@ export type ComponentModelStructure = {
}
>;
};
export type PieceModelCustomField = {
name: string;
value?: unknown;
type?: string;
required?: boolean;
options?: unknown;
};
export type PieceModelStructure = {
customFields?: PieceModelCustomField[];
[key: string]: unknown;
};