feat: Modules de gestion des entités principales - Ajout des modules Machines, Composants et Pièces avec leurs services et contrôleurs

This commit is contained in:
Matthieu
2025-07-29 21:04:08 +02:00
parent f8278aa40e
commit 564cfc8bdb
15 changed files with 1397 additions and 0 deletions

View File

@@ -0,0 +1,773 @@
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { CreateMachineDto, UpdateMachineDto } from '../shared/dto/machine.dto';
@Injectable()
export class MachinesService {
constructor(private prisma: PrismaService) {}
async create(createMachineDto: CreateMachineDto) {
// Récupérer le type de machine pour hériter de sa structure
const typeMachine = await this.prisma.typeMachine.findUnique({
where: { id: createMachineDto.typeMachineId },
include: {
customFields: true,
},
});
if (!typeMachine) {
throw new Error('Type de machine non trouvé');
}
// Créer la machine avec la structure héritée du type
return await this.prisma.$transaction(async (prisma) => {
// 1. Créer la machine
const machine = await prisma.machine.create({
data: createMachineDto,
include: {
site: true,
typeMachine: true,
},
});
// 2. Créer les composants basés sur la structure du type
const components = (typeMachine as any).components;
if (components) {
await this.createComponentsFromType(prisma, machine.id, components);
}
// 3. Créer les pièces de machine basées sur le type
const machinePieces = (typeMachine as any).machinePieces;
if (machinePieces) {
await this.createMachinePiecesFromType(prisma, machine.id, machinePieces);
}
// 4. Créer les champs personnalisés de la machine basés sur le type
if (typeMachine.customFields && typeMachine.customFields.length > 0) {
await this.createMachineCustomFieldsFromType(prisma, machine.id, typeMachine.customFields);
}
// 5. Retourner la machine avec sa structure complète
return await prisma.machine.findUnique({
where: { id: machine.id },
include: {
site: true,
typeMachine: {
include: {
customFields: true,
},
},
composants: {
include: {
typeComposant: true,
sousComposants: true,
pieces: {
include: {
customFieldValues: {
include: {
customField: true,
},
},
},
},
},
},
pieces: {
include: {
customFieldValues: {
include: {
customField: true,
},
},
},
},
customFieldValues: {
include: {
customField: true,
},
},
documents: true,
},
});
});
}
private async createComponentsFromType(prisma: any, machineId: string, components: any[], parentComposantId?: string) {
for (const component of components) {
if (!component.name) continue;
// Créer d'abord le type de composant s'il n'existe pas
let typeComposant: any = null;
if (component.customFields && component.customFields.length > 0) {
// Chercher d'abord si le type de composant existe déjà
typeComposant = await prisma.typeComposant.findFirst({
where: { name: component.name }
});
// Si le type n'existe pas, le créer
if (!typeComposant) {
typeComposant = await prisma.typeComposant.create({
data: {
name: component.name,
description: component.description || '',
},
});
// Créer les champs personnalisés pour le type de composant
for (const customField of component.customFields) {
await prisma.customField.create({
data: {
name: customField.name,
type: customField.type,
required: customField.required || false,
defaultValue: customField.defaultValue,
options: customField.options || [],
typeComposantId: typeComposant.id,
},
});
}
}
}
const createdComposant = await prisma.composant.create({
data: {
name: component.name,
reference: component.reference || '',
prestataire: component.prestataire || '',
emplacement: component.emplacement || '',
prix: component.prix || null,
machineId,
parentComposantId,
typeComposantId: typeComposant?.id || null,
},
});
// Créer les valeurs des champs personnalisés pour le composant
if (typeComposant && typeComposant.id) {
const customFields = await prisma.customField.findMany({
where: { typeComposantId: typeComposant.id },
});
for (const customField of customFields) {
const defaultValue = component.customFields?.find(cf => cf.name === customField.name)?.defaultValue || '';
await prisma.customFieldValue.create({
data: {
value: defaultValue,
customFieldId: customField.id,
composantId: createdComposant.id,
},
});
}
}
// Créer les pièces du composant avec leurs champs personnalisés
if (component.pieces) {
for (const piece of component.pieces) {
if (!piece || !piece.name) continue;
// Créer d'abord le type de pièce s'il n'existe pas
let typePiece: any = null;
if (piece.customFields && piece.customFields.length > 0) {
// Chercher d'abord si le type de pièce existe déjà
typePiece = await prisma.typePiece.findFirst({
where: { name: piece.name }
});
// Si le type n'existe pas, le créer
if (!typePiece) {
typePiece = await prisma.typePiece.create({
data: {
name: piece.name,
description: piece.description || '',
},
});
// Créer les champs personnalisés pour le type de pièce
for (const customField of piece.customFields) {
await prisma.customField.create({
data: {
name: customField.name,
type: customField.type,
required: customField.required || false,
defaultValue: customField.defaultValue,
options: customField.options || [],
typePieceId: typePiece.id,
},
});
}
}
}
const createdPiece = await prisma.piece.create({
data: {
name: piece.name,
reference: piece.reference || '',
prestataire: piece.prestataire || '',
emplacement: piece.emplacement || '',
prix: piece.prix || null,
composantId: createdComposant.id,
typePieceId: typePiece?.id || null,
},
});
// Créer les valeurs des champs personnalisés pour la pièce
if (typePiece && typePiece.id) {
const customFields = await prisma.customField.findMany({
where: { typePieceId: typePiece.id },
});
for (const customField of customFields) {
const defaultValue = piece.customFields?.find(cf => cf.name === customField.name)?.defaultValue || '';
await prisma.customFieldValue.create({
data: {
value: defaultValue,
customFieldId: customField.id,
pieceId: createdPiece.id,
},
});
}
}
}
}
// Créer les sous-composants récursivement
if (component.subComponents) {
await this.createComponentsFromType(prisma, machineId, component.subComponents, createdComposant.id);
}
}
}
private async createMachinePiecesFromType(prisma: any, machineId: string, machinePieces: any[]) {
for (const piece of machinePieces) {
if (!piece || !piece.name) continue;
const createdPiece = await prisma.piece.create({
data: {
name: piece.name,
machineId,
},
});
// Copier les champs personnalisés du type vers la pièce
if (piece.customFields && piece.customFields.length > 0) {
for (const customField of piece.customFields) {
// Créer le champ personnalisé
const createdCustomField = await prisma.customField.create({
data: {
name: customField.name,
type: customField.type,
required: customField.required || false,
defaultValue: customField.defaultValue,
options: customField.options || [],
typePieceId: null, // Ce champ sera lié à la pièce individuelle
},
});
// Créer la valeur par défaut
await prisma.customFieldValue.create({
data: {
value: customField.defaultValue || '',
customFieldId: createdCustomField.id,
pieceId: createdPiece.id,
},
});
}
}
}
}
private async createMachineCustomFieldsFromType(prisma: any, machineId: string, machineCustomFields: any[]) {
for (const customField of machineCustomFields) {
if (!customField || !customField.name) continue;
// Créer le champ personnalisé pour la machine
const createdCustomField = await prisma.customField.create({
data: {
name: customField.name,
type: customField.type,
required: customField.required || false,
defaultValue: customField.defaultValue,
options: customField.options || [],
typeMachineId: null, // Ce champ sera lié à la machine individuelle
},
});
// Créer la valeur par défaut pour la machine
await prisma.customFieldValue.create({
data: {
value: customField.defaultValue || '',
customFieldId: createdCustomField.id,
machineId: machineId,
},
});
}
}
async findAll() {
return this.prisma.machine.findMany({
include: {
site: true,
typeMachine: {
include: {
customFields: true,
},
},
composants: {
include: {
typeComposant: true,
sousComposants: true,
customFieldValues: {
include: {
customField: true,
},
},
pieces: {
include: {
customFieldValues: {
include: {
customField: true,
},
},
},
},
},
},
pieces: {
include: {
customFieldValues: {
include: {
customField: true,
},
},
},
},
customFieldValues: {
include: {
customField: true,
},
},
documents: true,
},
});
}
async findOne(id: string) {
return this.prisma.machine.findUnique({
where: { id },
include: {
site: true,
typeMachine: {
include: {
customFields: true,
},
},
composants: {
include: {
typeComposant: true,
sousComposants: true,
customFieldValues: {
include: {
customField: true,
},
},
pieces: {
include: {
customFieldValues: {
include: {
customField: true,
},
},
},
},
},
},
pieces: {
include: {
customFieldValues: {
include: {
customField: true,
},
},
},
},
customFieldValues: {
include: {
customField: true,
},
},
documents: true,
},
});
}
async update(id: string, updateMachineDto: UpdateMachineDto) {
return this.prisma.machine.update({
where: { id },
data: updateMachineDto,
include: {
site: true,
typeMachine: {
include: {
customFields: true,
},
},
composants: {
include: {
typeComposant: true,
sousComposants: true,
pieces: true,
},
},
pieces: true,
customFieldValues: {
include: {
customField: true,
},
},
documents: true,
},
});
}
async remove(id: string) {
// Vérifier que la machine existe
const machine = await this.prisma.machine.findUnique({
where: { id },
include: {
composants: true,
pieces: true,
documents: true,
customFieldValues: true,
},
});
if (!machine) {
throw new Error('Machine non trouvée');
}
// Supprimer la machine et tous ses éléments associés en cascade
return await this.prisma.$transaction(async (prisma) => {
// Supprimer les valeurs de champs personnalisés
if (machine.customFieldValues.length > 0) {
await prisma.customFieldValue.deleteMany({
where: { machineId: id },
});
}
// Supprimer les documents
if (machine.documents.length > 0) {
await prisma.document.deleteMany({
where: { machineId: id },
});
}
// Supprimer les pièces (sera fait en cascade via la relation)
if (machine.pieces.length > 0) {
await prisma.piece.deleteMany({
where: { machineId: id },
});
}
// Supprimer les composants (sera fait en cascade via la relation)
if (machine.composants.length > 0) {
await prisma.composant.deleteMany({
where: { machineId: id },
});
}
// Supprimer la machine
return await prisma.machine.delete({
where: { id },
});
});
}
// Méthode pour ajouter les champs personnalisés manquants aux composants et pièces existants
async addMissingCustomFields(machineId: string) {
const machine = await this.prisma.machine.findUnique({
where: { id: machineId },
include: {
typeMachine: true,
composants: {
include: {
pieces: true,
},
},
pieces: true,
},
});
if (!machine || !machine.typeMachine) {
throw new Error('Machine ou type de machine non trouvé');
}
const typeMachine = machine.typeMachine as any;
const components = typeMachine.components || [];
const machinePieces = typeMachine.machinePieces || [];
const machineCustomFields = typeMachine.customFields || [];
// Traiter les champs personnalisés de la machine
if (machineCustomFields && machineCustomFields.length > 0) {
for (const customField of machineCustomFields) {
const existingValue = await this.prisma.customFieldValue.findFirst({
where: {
machineId: machineId,
customField: {
name: customField.name,
},
},
include: {
customField: true,
},
});
if (!existingValue) {
// Créer le champ personnalisé pour la machine
const createdCustomField = await this.prisma.customField.create({
data: {
name: customField.name,
type: customField.type,
required: customField.required || false,
defaultValue: customField.defaultValue,
options: customField.options || [],
typeMachineId: null, // Ce champ sera lié à la machine individuelle
},
});
// Créer la valeur par défaut pour la machine
await this.prisma.customFieldValue.create({
data: {
value: customField.defaultValue || '',
customFieldId: createdCustomField.id,
machineId: machineId,
},
});
}
}
}
// Traiter les composants existants
for (const component of machine.composants) {
const typeComponent = components.find((c: any) => c.name === component.name);
if (typeComponent && typeComponent.customFields && typeComponent.customFields.length > 0) {
// Créer le type de composant s'il n'existe pas
let typeComposant = await this.prisma.typeComposant.findFirst({
where: { name: component.name },
});
if (!typeComposant) {
typeComposant = await this.prisma.typeComposant.create({
data: {
name: component.name,
description: typeComponent.description || '',
},
});
}
// Créer les champs personnalisés pour le type de composant
for (const customField of typeComponent.customFields) {
const existingField = await this.prisma.customField.findFirst({
where: {
name: customField.name,
typeComposantId: typeComposant.id,
},
});
if (!existingField) {
await this.prisma.customField.create({
data: {
name: customField.name,
type: customField.type,
required: customField.required || false,
defaultValue: customField.defaultValue,
options: customField.options || [],
typeComposantId: typeComposant.id,
},
});
}
}
// Mettre à jour le composant avec le type
await this.prisma.composant.update({
where: { id: component.id },
data: { typeComposantId: typeComposant.id },
});
// Créer les valeurs des champs personnalisés pour le composant
const customFields = await this.prisma.customField.findMany({
where: { typeComposantId: typeComposant.id },
});
for (const customField of customFields) {
const existingValue = await this.prisma.customFieldValue.findFirst({
where: {
customFieldId: customField.id,
composantId: component.id,
},
});
if (!existingValue) {
const defaultValue = typeComponent.customFields.find((cf: any) => cf.name === customField.name)?.defaultValue || '';
await this.prisma.customFieldValue.create({
data: {
value: defaultValue,
customFieldId: customField.id,
composantId: component.id,
},
});
}
}
// Traiter les pièces du composant
for (const piece of component.pieces) {
const typePiece = typeComponent.pieces?.find((p: any) => p.name === piece.name);
if (typePiece && typePiece.customFields && typePiece.customFields.length > 0) {
// Créer le type de pièce s'il n'existe pas
let typePieceEntity = await this.prisma.typePiece.findFirst({
where: { name: piece.name },
});
if (!typePieceEntity) {
typePieceEntity = await this.prisma.typePiece.create({
data: {
name: piece.name,
description: typePiece.description || '',
},
});
}
// Créer les champs personnalisés pour le type de pièce
for (const customField of typePiece.customFields) {
const existingField = await this.prisma.customField.findFirst({
where: {
name: customField.name,
typePieceId: typePieceEntity.id,
},
});
if (!existingField) {
await this.prisma.customField.create({
data: {
name: customField.name,
type: customField.type,
required: customField.required || false,
defaultValue: customField.defaultValue,
options: customField.options || [],
typePieceId: typePieceEntity.id,
},
});
}
}
// Mettre à jour la pièce avec le type
await this.prisma.piece.update({
where: { id: piece.id },
data: { typePieceId: typePieceEntity.id },
});
// Créer les valeurs des champs personnalisés pour la pièce
const customFields = await this.prisma.customField.findMany({
where: { typePieceId: typePieceEntity.id },
});
for (const customField of customFields) {
const existingValue = await this.prisma.customFieldValue.findFirst({
where: {
customFieldId: customField.id,
pieceId: piece.id,
},
});
if (!existingValue) {
const defaultValue = typePiece.customFields.find((cf: any) => cf.name === customField.name)?.defaultValue || '';
await this.prisma.customFieldValue.create({
data: {
value: defaultValue,
customFieldId: customField.id,
pieceId: piece.id,
},
});
}
}
}
}
}
}
// Traiter les pièces de machine
for (const piece of machine.pieces) {
const typePiece = machinePieces.find((p: any) => p.name === piece.name);
if (typePiece && typePiece.customFields && typePiece.customFields.length > 0) {
// Créer le type de pièce s'il n'existe pas
let typePieceEntity = await this.prisma.typePiece.findFirst({
where: { name: piece.name },
});
if (!typePieceEntity) {
typePieceEntity = await this.prisma.typePiece.create({
data: {
name: piece.name,
description: typePiece.description || '',
},
});
}
// Créer les champs personnalisés pour le type de pièce
for (const customField of typePiece.customFields) {
const existingField = await this.prisma.customField.findFirst({
where: {
name: customField.name,
typePieceId: typePieceEntity.id,
},
});
if (!existingField) {
await this.prisma.customField.create({
data: {
name: customField.name,
type: customField.type,
required: customField.required || false,
defaultValue: customField.defaultValue,
options: customField.options || [],
typePieceId: typePieceEntity.id,
},
});
}
}
// Mettre à jour la pièce avec le type
await this.prisma.piece.update({
where: { id: piece.id },
data: { typePieceId: typePieceEntity.id },
});
// Créer les valeurs des champs personnalisés pour la pièce
const customFields = await this.prisma.customField.findMany({
where: { typePieceId: typePieceEntity.id },
});
for (const customField of customFields) {
const existingValue = await this.prisma.customFieldValue.findFirst({
where: {
customFieldId: customField.id,
pieceId: piece.id,
},
});
if (!existingValue) {
const defaultValue = typePiece.customFields.find((cf: any) => cf.name === customField.name)?.defaultValue || '';
await this.prisma.customFieldValue.create({
data: {
value: defaultValue,
customFieldId: customField.id,
pieceId: piece.id,
},
});
}
}
}
}
return this.findOne(machineId);
}
}