diff --git a/src/composants/composants.controller.spec.ts b/src/composants/composants.controller.spec.ts new file mode 100644 index 0000000..a78346e --- /dev/null +++ b/src/composants/composants.controller.spec.ts @@ -0,0 +1,21 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { ComposantsController } from './composants.controller'; +import { ComposantsService } from './composants.service'; +import { PrismaService } from '../prisma/prisma.service'; + +describe('ComposantsController', () => { + let controller: ComposantsController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [ComposantsController], + providers: [ComposantsService, PrismaService], + }).compile(); + + controller = module.get(ComposantsController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/composants/composants.controller.ts b/src/composants/composants.controller.ts new file mode 100644 index 0000000..a01daa3 --- /dev/null +++ b/src/composants/composants.controller.ts @@ -0,0 +1,43 @@ +import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; +import { ComposantsService } from './composants.service'; +import { CreateComposantDto, UpdateComposantDto } from '../shared/dto/composant.dto'; + +@Controller('composants') +export class ComposantsController { + constructor(private readonly composantsService: ComposantsService) {} + + @Post() + create(@Body() createComposantDto: CreateComposantDto) { + return this.composantsService.create(createComposantDto); + } + + @Get() + findAll() { + return this.composantsService.findAll(); + } + + @Get('hierarchy/:machineId') + findHierarchy(@Param('machineId') machineId: string) { + return this.composantsService.findHierarchy(machineId); + } + + @Get('machine/:machineId') + findByMachine(@Param('machineId') machineId: string) { + return this.composantsService.findByMachine(machineId); + } + + @Get(':id') + findOne(@Param('id') id: string) { + return this.composantsService.findOne(id); + } + + @Patch(':id') + update(@Param('id') id: string, @Body() updateComposantDto: UpdateComposantDto) { + return this.composantsService.update(id, updateComposantDto); + } + + @Delete(':id') + remove(@Param('id') id: string) { + return this.composantsService.remove(id); + } +} diff --git a/src/composants/composants.module.ts b/src/composants/composants.module.ts new file mode 100644 index 0000000..f970c8c --- /dev/null +++ b/src/composants/composants.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { ComposantsController } from './composants.controller'; +import { ComposantsService } from './composants.service'; + +@Module({ + controllers: [ComposantsController], + providers: [ComposantsService] +}) +export class ComposantsModule {} diff --git a/src/composants/composants.service.spec.ts b/src/composants/composants.service.spec.ts new file mode 100644 index 0000000..1ee01cc --- /dev/null +++ b/src/composants/composants.service.spec.ts @@ -0,0 +1,19 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { ComposantsService } from './composants.service'; +import { PrismaService } from '../prisma/prisma.service'; + +describe('ComposantsService', () => { + let service: ComposantsService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ComposantsService, PrismaService], + }).compile(); + + service = module.get(ComposantsService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/composants/composants.service.ts b/src/composants/composants.service.ts new file mode 100644 index 0000000..aea948f --- /dev/null +++ b/src/composants/composants.service.ts @@ -0,0 +1,267 @@ +import { Injectable } from '@nestjs/common'; +import { PrismaService } from '../prisma/prisma.service'; +import { CreateComposantDto, UpdateComposantDto } from '../shared/dto/composant.dto'; + +@Injectable() +export class ComposantsService { + constructor(private prisma: PrismaService) {} + + async create(createComposantDto: CreateComposantDto) { + return this.prisma.composant.create({ + data: createComposantDto, + include: { + machine: true, + parentComposant: true, + typeComposant: true, + sousComposants: { + include: { + typeComposant: true, + pieces: true, + }, + }, + pieces: true, + documents: true, + }, + }); + } + + async findAll() { + return this.prisma.composant.findMany({ + include: { + machine: true, + parentComposant: true, + typeComposant: true, + customFieldValues: { + include: { + customField: true, + }, + }, + sousComposants: { + include: { + typeComposant: true, + customFieldValues: { + include: { + customField: true, + }, + }, + pieces: { + include: { + customFieldValues: { + include: { + customField: true, + }, + }, + }, + }, + }, + }, + pieces: { + include: { + customFieldValues: { + include: { + customField: true, + }, + }, + }, + }, + documents: true, + }, + }); + } + + async findOne(id: string) { + return this.prisma.composant.findUnique({ + where: { id }, + include: { + machine: true, + parentComposant: true, + typeComposant: true, + customFieldValues: { + include: { + customField: true, + }, + }, + sousComposants: { + include: { + typeComposant: true, + customFieldValues: { + include: { + customField: true, + }, + }, + pieces: { + include: { + customFieldValues: { + include: { + customField: true, + }, + }, + }, + }, + }, + }, + pieces: { + include: { + customFieldValues: { + include: { + customField: true, + }, + }, + }, + }, + documents: true, + }, + }); + } + + async findByMachine(machineId: string) { + return this.prisma.composant.findMany({ + where: { machineId }, + include: { + machine: true, + parentComposant: true, + typeComposant: true, + sousComposants: { + include: { + typeComposant: true, + pieces: true, + }, + }, + pieces: { + include: { + customFieldValues: { + include: { + customField: true, + }, + }, + }, + }, + customFieldValues: { + include: { + customField: true, + }, + }, + documents: true, + }, + }); + } + + async findHierarchy(machineId: string) { + // Récupérer tous les composants de premier niveau (sans parent) + const rootComposants = await this.prisma.composant.findMany({ + where: { + machineId, + parentComposantId: null + }, + include: { + typeComposant: true, + customFieldValues: { + include: { + customField: true, + }, + }, + sousComposants: { + include: { + typeComposant: true, + customFieldValues: { + include: { + customField: true, + }, + }, + pieces: { + include: { + customFieldValues: { + include: { + customField: true, + }, + }, + }, + }, + sousComposants: { + include: { + typeComposant: true, + customFieldValues: { + include: { + customField: true, + }, + }, + pieces: { + include: { + customFieldValues: { + include: { + customField: true, + }, + }, + }, + }, + }, + }, + }, + }, + pieces: { + include: { + customFieldValues: { + include: { + customField: true, + }, + }, + }, + }, + }, + }); + + return rootComposants; + } + + async update(id: string, updateComposantDto: UpdateComposantDto) { + return this.prisma.composant.update({ + where: { id }, + data: updateComposantDto, + include: { + machine: true, + parentComposant: true, + typeComposant: true, + customFieldValues: { + include: { + customField: true, + }, + }, + sousComposants: { + include: { + typeComposant: true, + customFieldValues: { + include: { + customField: true, + }, + }, + pieces: { + include: { + customFieldValues: { + include: { + customField: true, + }, + }, + }, + }, + }, + }, + pieces: { + include: { + customFieldValues: { + include: { + customField: true, + }, + }, + }, + }, + documents: true, + }, + }); + } + + async remove(id: string) { + return this.prisma.composant.delete({ + where: { id }, + }); + } +} diff --git a/src/machines/machines.controller.spec.ts b/src/machines/machines.controller.spec.ts new file mode 100644 index 0000000..c6757a0 --- /dev/null +++ b/src/machines/machines.controller.spec.ts @@ -0,0 +1,21 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { MachinesController } from './machines.controller'; +import { MachinesService } from './machines.service'; +import { PrismaService } from '../prisma/prisma.service'; + +describe('MachinesController', () => { + let controller: MachinesController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [MachinesController], + providers: [MachinesService, PrismaService], + }).compile(); + + controller = module.get(MachinesController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/machines/machines.controller.ts b/src/machines/machines.controller.ts new file mode 100644 index 0000000..4988f4b --- /dev/null +++ b/src/machines/machines.controller.ts @@ -0,0 +1,38 @@ +import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; +import { MachinesService } from './machines.service'; +import { CreateMachineDto, UpdateMachineDto } from '../shared/dto/machine.dto'; + +@Controller('machines') +export class MachinesController { + constructor(private readonly machinesService: MachinesService) {} + + @Post() + create(@Body() createMachineDto: CreateMachineDto) { + return this.machinesService.create(createMachineDto); + } + + @Get() + findAll() { + return this.machinesService.findAll(); + } + + @Get(':id') + findOne(@Param('id') id: string) { + return this.machinesService.findOne(id); + } + + @Patch(':id') + update(@Param('id') id: string, @Body() updateMachineDto: UpdateMachineDto) { + return this.machinesService.update(id, updateMachineDto); + } + + @Delete(':id') + remove(@Param('id') id: string) { + return this.machinesService.remove(id); + } + + @Post(':id/add-custom-fields') + addMissingCustomFields(@Param('id') id: string) { + return this.machinesService.addMissingCustomFields(id); + } +} diff --git a/src/machines/machines.module.ts b/src/machines/machines.module.ts new file mode 100644 index 0000000..f118532 --- /dev/null +++ b/src/machines/machines.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { MachinesController } from './machines.controller'; +import { MachinesService } from './machines.service'; + +@Module({ + controllers: [MachinesController], + providers: [MachinesService] +}) +export class MachinesModule {} diff --git a/src/machines/machines.service.spec.ts b/src/machines/machines.service.spec.ts new file mode 100644 index 0000000..376099f --- /dev/null +++ b/src/machines/machines.service.spec.ts @@ -0,0 +1,19 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { MachinesService } from './machines.service'; +import { PrismaService } from '../prisma/prisma.service'; + +describe('MachinesService', () => { + let service: MachinesService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [MachinesService, PrismaService], + }).compile(); + + service = module.get(MachinesService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/machines/machines.service.ts b/src/machines/machines.service.ts new file mode 100644 index 0000000..878b3bd --- /dev/null +++ b/src/machines/machines.service.ts @@ -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); + } +} diff --git a/src/pieces/pieces.controller.spec.ts b/src/pieces/pieces.controller.spec.ts new file mode 100644 index 0000000..3d65b7e --- /dev/null +++ b/src/pieces/pieces.controller.spec.ts @@ -0,0 +1,21 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { PiecesController } from './pieces.controller'; +import { PiecesService } from './pieces.service'; +import { PrismaService } from '../prisma/prisma.service'; + +describe('PiecesController', () => { + let controller: PiecesController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [PiecesController], + providers: [PiecesService, PrismaService], + }).compile(); + + controller = module.get(PiecesController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/pieces/pieces.controller.ts b/src/pieces/pieces.controller.ts new file mode 100644 index 0000000..a03f4bf --- /dev/null +++ b/src/pieces/pieces.controller.ts @@ -0,0 +1,43 @@ +import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common'; +import { PiecesService } from './pieces.service'; +import { CreatePieceDto, UpdatePieceDto } from '../shared/dto/piece.dto'; + +@Controller('pieces') +export class PiecesController { + constructor(private readonly piecesService: PiecesService) {} + + @Post() + create(@Body() createPieceDto: CreatePieceDto) { + return this.piecesService.create(createPieceDto); + } + + @Get() + findAll() { + return this.piecesService.findAll(); + } + + @Get('machine/:machineId') + findByMachine(@Param('machineId') machineId: string) { + return this.piecesService.findByMachine(machineId); + } + + @Get('composant/:composantId') + findByComposant(@Param('composantId') composantId: string) { + return this.piecesService.findByComposant(composantId); + } + + @Get(':id') + findOne(@Param('id') id: string) { + return this.piecesService.findOne(id); + } + + @Patch(':id') + update(@Param('id') id: string, @Body() updatePieceDto: UpdatePieceDto) { + return this.piecesService.update(id, updatePieceDto); + } + + @Delete(':id') + remove(@Param('id') id: string) { + return this.piecesService.remove(id); + } +} diff --git a/src/pieces/pieces.module.ts b/src/pieces/pieces.module.ts new file mode 100644 index 0000000..36c953d --- /dev/null +++ b/src/pieces/pieces.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; +import { PiecesController } from './pieces.controller'; +import { PiecesService } from './pieces.service'; + +@Module({ + controllers: [PiecesController], + providers: [PiecesService] +}) +export class PiecesModule {} diff --git a/src/pieces/pieces.service.spec.ts b/src/pieces/pieces.service.spec.ts new file mode 100644 index 0000000..8fe3047 --- /dev/null +++ b/src/pieces/pieces.service.spec.ts @@ -0,0 +1,19 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { PiecesService } from './pieces.service'; +import { PrismaService } from '../prisma/prisma.service'; + +describe('PiecesService', () => { + let service: PiecesService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [PiecesService, PrismaService], + }).compile(); + + service = module.get(PiecesService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/src/pieces/pieces.service.ts b/src/pieces/pieces.service.ts new file mode 100644 index 0000000..b6df1d7 --- /dev/null +++ b/src/pieces/pieces.service.ts @@ -0,0 +1,86 @@ +import { Injectable } from '@nestjs/common'; +import { PrismaService } from '../prisma/prisma.service'; +import { CreatePieceDto, UpdatePieceDto } from '../shared/dto/piece.dto'; + +@Injectable() +export class PiecesService { + constructor(private prisma: PrismaService) {} + + async create(createPieceDto: CreatePieceDto) { + return this.prisma.piece.create({ + data: createPieceDto, + include: { + machine: true, + composant: true, + typePiece: true, + documents: true, + }, + }); + } + + async findAll() { + return this.prisma.piece.findMany({ + include: { + machine: true, + composant: true, + typePiece: true, + documents: true, + }, + }); + } + + async findOne(id: string) { + return this.prisma.piece.findUnique({ + where: { id }, + include: { + machine: true, + composant: true, + typePiece: true, + documents: true, + }, + }); + } + + async findByMachine(machineId: string) { + return this.prisma.piece.findMany({ + where: { machineId }, + include: { + machine: true, + composant: true, + typePiece: true, + documents: true, + }, + }); + } + + async findByComposant(composantId: string) { + return this.prisma.piece.findMany({ + where: { composantId }, + include: { + machine: true, + composant: true, + typePiece: true, + documents: true, + }, + }); + } + + async update(id: string, updatePieceDto: UpdatePieceDto) { + return this.prisma.piece.update({ + where: { id }, + data: updatePieceDto, + include: { + machine: true, + composant: true, + typePiece: true, + documents: true, + }, + }); + } + + async remove(id: string) { + return this.prisma.piece.delete({ + where: { id }, + }); + } +}