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:
21
src/composants/composants.controller.spec.ts
Normal file
21
src/composants/composants.controller.spec.ts
Normal file
@@ -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>(ComposantsController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
43
src/composants/composants.controller.ts
Normal file
43
src/composants/composants.controller.ts
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
9
src/composants/composants.module.ts
Normal file
9
src/composants/composants.module.ts
Normal file
@@ -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 {}
|
||||
19
src/composants/composants.service.spec.ts
Normal file
19
src/composants/composants.service.spec.ts
Normal file
@@ -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>(ComposantsService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
267
src/composants/composants.service.ts
Normal file
267
src/composants/composants.service.ts
Normal file
@@ -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 },
|
||||
});
|
||||
}
|
||||
}
|
||||
21
src/machines/machines.controller.spec.ts
Normal file
21
src/machines/machines.controller.spec.ts
Normal file
@@ -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>(MachinesController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
38
src/machines/machines.controller.ts
Normal file
38
src/machines/machines.controller.ts
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
9
src/machines/machines.module.ts
Normal file
9
src/machines/machines.module.ts
Normal file
@@ -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 {}
|
||||
19
src/machines/machines.service.spec.ts
Normal file
19
src/machines/machines.service.spec.ts
Normal file
@@ -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>(MachinesService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
773
src/machines/machines.service.ts
Normal file
773
src/machines/machines.service.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
21
src/pieces/pieces.controller.spec.ts
Normal file
21
src/pieces/pieces.controller.spec.ts
Normal file
@@ -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>(PiecesController);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(controller).toBeDefined();
|
||||
});
|
||||
});
|
||||
43
src/pieces/pieces.controller.ts
Normal file
43
src/pieces/pieces.controller.ts
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
9
src/pieces/pieces.module.ts
Normal file
9
src/pieces/pieces.module.ts
Normal file
@@ -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 {}
|
||||
19
src/pieces/pieces.service.spec.ts
Normal file
19
src/pieces/pieces.service.spec.ts
Normal file
@@ -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>(PiecesService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
||||
86
src/pieces/pieces.service.ts
Normal file
86
src/pieces/pieces.service.ts
Normal file
@@ -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 },
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user