feat: auto populate machine structures and seed sample data
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import {
|
||||
@@ -9,638 +9,99 @@ import {
|
||||
COMPONENT_WITH_RELATIONS_INCLUDE,
|
||||
ComposantWithRelations,
|
||||
} from '../common/constants/component-includes';
|
||||
import {
|
||||
buildComponentHierarchy,
|
||||
buildComponentSubtree,
|
||||
} from '../common/utils/component-tree.util';
|
||||
import { ComponentModelStructureSchema } from '../shared/schemas/inventory';
|
||||
import type { ComponentModelStructure } from '../shared/types/inventory';
|
||||
|
||||
type ComponentRequirementWithType =
|
||||
Prisma.TypeMachineComponentRequirementGetPayload<{
|
||||
include: { typeComposant: true };
|
||||
}>;
|
||||
type PieceRequirementWithType = Prisma.TypeMachinePieceRequirementGetPayload<{
|
||||
include: { typePiece: true };
|
||||
}>;
|
||||
type ModelTypeWithSkeleton = ComponentRequirementWithType['typeComposant'];
|
||||
type PieceTypeWithSkeleton = PieceRequirementWithType['typePiece'];
|
||||
|
||||
@Injectable()
|
||||
export class ComposantsService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
|
||||
private async fetchComponentsByMachine(
|
||||
machineId: string,
|
||||
): Promise<ComposantWithRelations[]> {
|
||||
return this.prisma.composant.findMany({
|
||||
where: { machineId },
|
||||
include: COMPONENT_WITH_RELATIONS_INCLUDE,
|
||||
}) as Promise<ComposantWithRelations[]>;
|
||||
}
|
||||
private buildCreateInput(
|
||||
createComposantDto: CreateComposantDto,
|
||||
): Prisma.ComposantCreateInput {
|
||||
const data: Prisma.ComposantCreateInput = {
|
||||
name: createComposantDto.name,
|
||||
reference: createComposantDto.reference ?? null,
|
||||
prix:
|
||||
createComposantDto.prix !== undefined ? createComposantDto.prix : null,
|
||||
};
|
||||
|
||||
private async getComponentWithHierarchy(
|
||||
id: string,
|
||||
): Promise<ComposantWithRelations | null> {
|
||||
const baseComponent = (await this.prisma.composant.findUnique({
|
||||
where: { id },
|
||||
include: COMPONENT_WITH_RELATIONS_INCLUDE,
|
||||
})) as ComposantWithRelations | null;
|
||||
|
||||
if (!baseComponent) {
|
||||
return null;
|
||||
if (createComposantDto.constructeurId) {
|
||||
data.constructeur = {
|
||||
connect: { id: createComposantDto.constructeurId },
|
||||
};
|
||||
}
|
||||
|
||||
if (!baseComponent.machineId) {
|
||||
baseComponent.sousComposants = [];
|
||||
return baseComponent;
|
||||
if (createComposantDto.typeComposantId) {
|
||||
data.typeComposant = {
|
||||
connect: { id: createComposantDto.typeComposantId },
|
||||
};
|
||||
}
|
||||
|
||||
const components = await this.fetchComponentsByMachine(
|
||||
baseComponent.machineId,
|
||||
);
|
||||
const subtree = buildComponentSubtree(components, id);
|
||||
return subtree ?? baseComponent;
|
||||
if (createComposantDto.structure !== undefined) {
|
||||
data.structure = createComposantDto.structure as Prisma.InputJsonValue;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async create(createComposantDto: CreateComposantDto) {
|
||||
const requirementId =
|
||||
createComposantDto.typeMachineComponentRequirementId ?? null;
|
||||
|
||||
if (requirementId && !createComposantDto.machineId) {
|
||||
throw new BadRequestException(
|
||||
'Un requirement ne peut pas être utilisé sans machine ciblée.',
|
||||
);
|
||||
}
|
||||
|
||||
let machineId = createComposantDto.machineId ?? null;
|
||||
|
||||
if (createComposantDto.parentComposantId) {
|
||||
const parentMachineId = await this.resolveMachineIdFromComposant(
|
||||
createComposantDto.parentComposantId,
|
||||
);
|
||||
|
||||
if (machineId && parentMachineId && machineId !== parentMachineId) {
|
||||
throw new BadRequestException(
|
||||
'Le composant parent ne correspond pas à la machine ciblée.',
|
||||
);
|
||||
}
|
||||
|
||||
machineId = parentMachineId ?? machineId;
|
||||
}
|
||||
|
||||
let requirement: ComponentRequirementWithType | null = null;
|
||||
let componentRequirements: ComponentRequirementWithType[] = [];
|
||||
let pieceRequirements: PieceRequirementWithType[] = [];
|
||||
|
||||
if (machineId) {
|
||||
const machine = await this.prisma.machine.findUnique({
|
||||
where: { id: machineId },
|
||||
include: {
|
||||
typeMachine: {
|
||||
include: {
|
||||
componentRequirements: {
|
||||
include: {
|
||||
typeComposant: true,
|
||||
},
|
||||
},
|
||||
pieceRequirements: {
|
||||
include: {
|
||||
typePiece: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!machine || !machine.typeMachine) {
|
||||
throw new BadRequestException(
|
||||
'La machine ciblée doit être associée à un type de machine pour valider les requirements.',
|
||||
);
|
||||
}
|
||||
|
||||
componentRequirements =
|
||||
(machine.typeMachine
|
||||
.componentRequirements as ComponentRequirementWithType[]) ?? [];
|
||||
pieceRequirements =
|
||||
(machine.typeMachine.pieceRequirements as PieceRequirementWithType[]) ??
|
||||
[];
|
||||
|
||||
if (requirementId) {
|
||||
requirement =
|
||||
componentRequirements.find(
|
||||
(componentRequirement) => componentRequirement.id === requirementId,
|
||||
) ?? null;
|
||||
|
||||
if (!requirement) {
|
||||
throw new BadRequestException(
|
||||
'Le requirement de composant fourni ne correspond pas au squelette de la machine.',
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
createComposantDto.typeComposantId &&
|
||||
createComposantDto.typeComposantId !== requirement.typeComposantId
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
'Le type de composant fourni ne correspond pas au requirement pour cette machine.',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const typeComposantId =
|
||||
createComposantDto.typeComposantId ??
|
||||
requirement?.typeComposantId ??
|
||||
null;
|
||||
|
||||
const data: Prisma.ComposantUncheckedCreateInput = {
|
||||
name: createComposantDto.name,
|
||||
reference: createComposantDto.reference ?? null,
|
||||
constructeurId: createComposantDto.constructeurId ?? null,
|
||||
prix:
|
||||
createComposantDto.prix !== undefined ? createComposantDto.prix : null,
|
||||
machineId,
|
||||
parentComposantId: createComposantDto.parentComposantId ?? null,
|
||||
typeComposantId,
|
||||
typeMachineComponentRequirementId:
|
||||
requirement?.id ?? requirementId ?? null,
|
||||
};
|
||||
|
||||
const created = (await this.prisma.composant.create({
|
||||
data,
|
||||
const created = await this.prisma.composant.create({
|
||||
data: this.buildCreateInput(createComposantDto),
|
||||
include: COMPONENT_WITH_RELATIONS_INCLUDE,
|
||||
})) as ComposantWithRelations;
|
||||
});
|
||||
|
||||
if (machineId && requirement?.id) {
|
||||
const componentRequirementUsage = new Map<string, number>();
|
||||
componentRequirementUsage.set(requirement.id, 1);
|
||||
const pieceRequirementUsage = new Map<string, number>();
|
||||
|
||||
await this.populateComponentFromSkeleton({
|
||||
componentId: created.id,
|
||||
componentName: created.name,
|
||||
componentType:
|
||||
(requirement.typeComposant as ModelTypeWithSkeleton | null) ??
|
||||
(created.typeComposant as ModelTypeWithSkeleton | null) ??
|
||||
null,
|
||||
machineId,
|
||||
componentRequirements,
|
||||
pieceRequirements,
|
||||
componentRequirementUsage,
|
||||
pieceRequirementUsage,
|
||||
});
|
||||
}
|
||||
|
||||
const component = await this.getComponentWithHierarchy(created.id);
|
||||
return component ?? created;
|
||||
return created as ComposantWithRelations;
|
||||
}
|
||||
|
||||
async findAll() {
|
||||
const components = (await this.prisma.composant.findMany({
|
||||
return (await this.prisma.composant.findMany({
|
||||
include: COMPONENT_WITH_RELATIONS_INCLUDE,
|
||||
orderBy: { name: 'asc' },
|
||||
})) as ComposantWithRelations[];
|
||||
|
||||
return buildComponentHierarchy(components);
|
||||
}
|
||||
|
||||
async findOne(id: string) {
|
||||
return this.getComponentWithHierarchy(id);
|
||||
}
|
||||
|
||||
async findByMachine(machineId: string) {
|
||||
const components = await this.fetchComponentsByMachine(machineId);
|
||||
return buildComponentHierarchy(components);
|
||||
}
|
||||
|
||||
async findHierarchy(machineId: string) {
|
||||
const components = await this.fetchComponentsByMachine(machineId);
|
||||
return buildComponentHierarchy(components);
|
||||
return (await this.prisma.composant.findUnique({
|
||||
where: { id },
|
||||
include: COMPONENT_WITH_RELATIONS_INCLUDE,
|
||||
})) as ComposantWithRelations | null;
|
||||
}
|
||||
|
||||
async update(id: string, updateComposantDto: UpdateComposantDto) {
|
||||
const updated = (await this.prisma.composant.update({
|
||||
const data: Prisma.ComposantUpdateInput = {};
|
||||
|
||||
if (updateComposantDto.name !== undefined) {
|
||||
data.name = updateComposantDto.name;
|
||||
}
|
||||
|
||||
if (updateComposantDto.reference !== undefined) {
|
||||
data.reference = updateComposantDto.reference;
|
||||
}
|
||||
|
||||
if (updateComposantDto.prix !== undefined) {
|
||||
data.prix = updateComposantDto.prix;
|
||||
}
|
||||
|
||||
if (updateComposantDto.constructeurId !== undefined) {
|
||||
data.constructeur = updateComposantDto.constructeurId
|
||||
? { connect: { id: updateComposantDto.constructeurId } }
|
||||
: { disconnect: true };
|
||||
}
|
||||
|
||||
if (updateComposantDto.typeComposantId !== undefined) {
|
||||
data.typeComposant = updateComposantDto.typeComposantId
|
||||
? { connect: { id: updateComposantDto.typeComposantId } }
|
||||
: { disconnect: true };
|
||||
}
|
||||
|
||||
if (updateComposantDto.structure !== undefined) {
|
||||
data.structure = updateComposantDto.structure as Prisma.InputJsonValue;
|
||||
}
|
||||
|
||||
return (await this.prisma.composant.update({
|
||||
where: { id },
|
||||
data: updateComposantDto,
|
||||
data,
|
||||
include: COMPONENT_WITH_RELATIONS_INCLUDE,
|
||||
})) as ComposantWithRelations;
|
||||
|
||||
return this.getComponentWithHierarchy(updated.id);
|
||||
}
|
||||
|
||||
private async populateComponentFromSkeleton({
|
||||
componentId,
|
||||
componentName,
|
||||
componentType,
|
||||
machineId,
|
||||
componentRequirements,
|
||||
pieceRequirements,
|
||||
componentRequirementUsage,
|
||||
pieceRequirementUsage,
|
||||
}: {
|
||||
componentId: string;
|
||||
componentName?: string;
|
||||
componentType: ModelTypeWithSkeleton | null;
|
||||
machineId: string;
|
||||
componentRequirements: ComponentRequirementWithType[];
|
||||
pieceRequirements: PieceRequirementWithType[];
|
||||
componentRequirementUsage: Map<string, number>;
|
||||
pieceRequirementUsage: Map<string, number>;
|
||||
}) {
|
||||
const skeleton = this.parseComponentSkeleton(
|
||||
(componentType as { componentSkeleton?: Prisma.JsonValue | null } | null)
|
||||
?.componentSkeleton,
|
||||
);
|
||||
if (!skeleton) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.createComponentCustomFieldValues(
|
||||
componentId,
|
||||
componentType?.id ?? null,
|
||||
skeleton.customFields,
|
||||
);
|
||||
|
||||
await this.createPiecesFromSkeleton({
|
||||
componentId,
|
||||
componentName,
|
||||
machineId,
|
||||
pieces: skeleton.pieces,
|
||||
pieceRequirements,
|
||||
pieceRequirementUsage,
|
||||
});
|
||||
|
||||
for (const subcomponent of skeleton.subcomponents ?? []) {
|
||||
const requirement = this.resolveComponentRequirement(
|
||||
subcomponent,
|
||||
componentRequirements,
|
||||
componentRequirementUsage,
|
||||
);
|
||||
|
||||
if (!requirement?.typeComposant) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const name = this.buildComponentName(
|
||||
subcomponent,
|
||||
requirement.typeComposant,
|
||||
componentName,
|
||||
);
|
||||
|
||||
const createdChild = await this.prisma.composant.create({
|
||||
data: {
|
||||
name,
|
||||
machineId,
|
||||
parentComposantId: componentId,
|
||||
typeComposantId: requirement.typeComposantId,
|
||||
typeMachineComponentRequirementId: requirement.id,
|
||||
},
|
||||
});
|
||||
|
||||
this.incrementRequirementUsage(componentRequirementUsage, requirement.id);
|
||||
|
||||
await this.populateComponentFromSkeleton({
|
||||
componentId: createdChild.id,
|
||||
componentName: createdChild.name,
|
||||
componentType: requirement.typeComposant,
|
||||
machineId,
|
||||
componentRequirements,
|
||||
pieceRequirements,
|
||||
componentRequirementUsage,
|
||||
pieceRequirementUsage,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private parseComponentSkeleton(
|
||||
value: unknown,
|
||||
): ComponentModelStructure | null {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return ComponentModelStructureSchema.parse(value);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async createComponentCustomFieldValues(
|
||||
componentId: string,
|
||||
typeComposantId: string | null,
|
||||
customFields: ComponentModelStructure['customFields'],
|
||||
) {
|
||||
if (
|
||||
!typeComposantId ||
|
||||
!Array.isArray(customFields) ||
|
||||
customFields.length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const definitions = await this.prisma.customField.findMany({
|
||||
where: { typeComposantId },
|
||||
select: { id: true, name: true },
|
||||
});
|
||||
|
||||
if (definitions.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const definitionMap = new Map(
|
||||
definitions.map((field) => [field.name, field.id]),
|
||||
);
|
||||
const existingValues = await this.prisma.customFieldValue.findMany({
|
||||
where: { composantId: componentId },
|
||||
select: { customFieldId: true },
|
||||
});
|
||||
const existingIds = new Set(
|
||||
existingValues.map((value) => value.customFieldId),
|
||||
);
|
||||
|
||||
for (const field of customFields) {
|
||||
const key = this.normalizeIdentifier(field?.key);
|
||||
if (!key) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const definitionId = definitionMap.get(key);
|
||||
if (!definitionId || existingIds.has(definitionId)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await this.prisma.customFieldValue.create({
|
||||
data: {
|
||||
customFieldId: definitionId,
|
||||
composantId: componentId,
|
||||
value: this.toCustomFieldValue(field?.value),
|
||||
},
|
||||
});
|
||||
|
||||
existingIds.add(definitionId);
|
||||
}
|
||||
}
|
||||
|
||||
private async createPiecesFromSkeleton({
|
||||
componentId,
|
||||
componentName,
|
||||
machineId,
|
||||
pieces,
|
||||
pieceRequirements,
|
||||
pieceRequirementUsage,
|
||||
}: {
|
||||
componentId: string;
|
||||
componentName?: string;
|
||||
machineId: string;
|
||||
pieces: ComponentModelStructure['pieces'];
|
||||
pieceRequirements: PieceRequirementWithType[];
|
||||
pieceRequirementUsage: Map<string, number>;
|
||||
}) {
|
||||
if (!Array.isArray(pieces) || pieces.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const entry of pieces) {
|
||||
const requirement = this.resolvePieceRequirement(
|
||||
entry,
|
||||
pieceRequirements,
|
||||
pieceRequirementUsage,
|
||||
);
|
||||
|
||||
if (!requirement?.typePiece) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const name = this.buildPieceName(
|
||||
entry,
|
||||
requirement.typePiece,
|
||||
componentName,
|
||||
);
|
||||
|
||||
await this.prisma.piece.create({
|
||||
data: {
|
||||
name,
|
||||
machineId,
|
||||
composantId: componentId,
|
||||
typePieceId: requirement.typePieceId,
|
||||
typeMachinePieceRequirementId: requirement.id,
|
||||
},
|
||||
});
|
||||
|
||||
this.incrementRequirementUsage(pieceRequirementUsage, requirement.id);
|
||||
}
|
||||
}
|
||||
|
||||
private resolveComponentRequirement(
|
||||
entry: ComponentModelStructure['subcomponents'][number],
|
||||
requirements: ComponentRequirementWithType[],
|
||||
usage: Map<string, number>,
|
||||
): ComponentRequirementWithType | null {
|
||||
const typeComposantId = this.normalizeIdentifier(
|
||||
(entry as { typeComposantId?: string }).typeComposantId,
|
||||
);
|
||||
const familyCode = this.normalizeCode(
|
||||
(entry as { familyCode?: string }).familyCode,
|
||||
);
|
||||
|
||||
const candidates = requirements.filter((requirement) => {
|
||||
if (typeComposantId && requirement.typeComposantId === typeComposantId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (familyCode && requirement.typeComposant?.code) {
|
||||
return (
|
||||
this.normalizeCode(requirement.typeComposant.code) === familyCode
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (candidates.length === 0) {
|
||||
if (typeComposantId || familyCode) {
|
||||
throw new BadRequestException(
|
||||
`Aucun requirement de composant ne correspond au squelette (${typeComposantId ?? familyCode}).`,
|
||||
);
|
||||
}
|
||||
|
||||
throw new BadRequestException(
|
||||
'Le squelette du composant référence un sous-composant sans identifiant de type.',
|
||||
);
|
||||
}
|
||||
|
||||
for (const candidate of candidates) {
|
||||
if (this.hasRequirementCapacity(candidate, usage)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
|
||||
throw new BadRequestException(
|
||||
`La capacité maximale du requirement de composant (${typeComposantId ?? familyCode}) est atteinte pour la machine visée.`,
|
||||
);
|
||||
}
|
||||
|
||||
private resolvePieceRequirement(
|
||||
entry: ComponentModelStructure['pieces'][number],
|
||||
requirements: PieceRequirementWithType[],
|
||||
usage: Map<string, number>,
|
||||
): PieceRequirementWithType | null {
|
||||
const typePieceId = this.normalizeIdentifier(
|
||||
(entry as { typePieceId?: string }).typePieceId,
|
||||
);
|
||||
const familyCode = this.normalizeCode(
|
||||
(entry as { familyCode?: string }).familyCode,
|
||||
);
|
||||
|
||||
const candidates = requirements.filter((requirement) => {
|
||||
if (typePieceId && requirement.typePieceId === typePieceId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (familyCode && requirement.typePiece?.code) {
|
||||
return this.normalizeCode(requirement.typePiece.code) === familyCode;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (candidates.length === 0) {
|
||||
if (typePieceId || familyCode) {
|
||||
throw new BadRequestException(
|
||||
`Aucun requirement de pièce ne correspond au squelette (${typePieceId ?? familyCode}).`,
|
||||
);
|
||||
}
|
||||
|
||||
throw new BadRequestException(
|
||||
'Le squelette du composant référence une pièce sans identifiant de type.',
|
||||
);
|
||||
}
|
||||
|
||||
for (const candidate of candidates) {
|
||||
if (this.hasRequirementCapacity(candidate, usage)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
|
||||
throw new BadRequestException(
|
||||
`La capacité maximale du requirement de pièce (${typePieceId ?? familyCode}) est atteinte pour la machine visée.`,
|
||||
);
|
||||
}
|
||||
|
||||
private hasRequirementCapacity(
|
||||
requirement: { id: string; maxCount: number | null | undefined },
|
||||
usage: Map<string, number>,
|
||||
): boolean {
|
||||
const max = requirement.maxCount;
|
||||
if (max === null || max === undefined) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const current = usage.get(requirement.id) ?? 0;
|
||||
return current < max;
|
||||
}
|
||||
|
||||
private incrementRequirementUsage(usage: Map<string, number>, id: string) {
|
||||
usage.set(id, (usage.get(id) ?? 0) + 1);
|
||||
}
|
||||
|
||||
private buildComponentName(
|
||||
subcomponent: ComponentModelStructure['subcomponents'][number],
|
||||
typeComposant: ModelTypeWithSkeleton | null,
|
||||
parentName?: string,
|
||||
): string {
|
||||
const alias = this.normalizeIdentifier(
|
||||
(subcomponent as { alias?: string }).alias,
|
||||
);
|
||||
if (alias) {
|
||||
return alias;
|
||||
}
|
||||
|
||||
if (typeComposant?.name) {
|
||||
return typeComposant.name;
|
||||
}
|
||||
|
||||
if (parentName) {
|
||||
return `${parentName} - Sous-composant`;
|
||||
}
|
||||
|
||||
return 'Sous-composant';
|
||||
}
|
||||
|
||||
private buildPieceName(
|
||||
piece: ComponentModelStructure['pieces'][number],
|
||||
typePiece: PieceTypeWithSkeleton | null,
|
||||
componentName?: string,
|
||||
): string {
|
||||
const role = this.normalizeIdentifier((piece as { role?: string }).role);
|
||||
if (role) {
|
||||
return role;
|
||||
}
|
||||
|
||||
if (typePiece?.name) {
|
||||
return typePiece.name;
|
||||
}
|
||||
|
||||
if (componentName) {
|
||||
return `${componentName} - Pièce`;
|
||||
}
|
||||
|
||||
return 'Pièce';
|
||||
}
|
||||
|
||||
private normalizeIdentifier(value: unknown): string | null {
|
||||
if (typeof value !== 'string') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const trimmed = value.trim();
|
||||
return trimmed.length > 0 ? trimmed : null;
|
||||
}
|
||||
|
||||
private normalizeCode(value: unknown): string | null {
|
||||
const identifier = this.normalizeIdentifier(value);
|
||||
return identifier ? identifier.toLowerCase() : null;
|
||||
}
|
||||
|
||||
private toCustomFieldValue(value: unknown): string {
|
||||
if (value === undefined || value === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return String(value);
|
||||
}
|
||||
|
||||
private async resolveMachineIdFromComposant(
|
||||
composantId: string,
|
||||
): Promise<string> {
|
||||
const composant = await this.prisma.composant.findUnique({
|
||||
where: { id: composantId },
|
||||
select: {
|
||||
id: true,
|
||||
machineId: true,
|
||||
parentComposantId: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!composant) {
|
||||
throw new BadRequestException(
|
||||
'Le composant parent spécifié est introuvable.',
|
||||
);
|
||||
}
|
||||
|
||||
if (composant.machineId) {
|
||||
return composant.machineId;
|
||||
}
|
||||
|
||||
if (composant.parentComposantId) {
|
||||
return this.resolveMachineIdFromComposant(composant.parentComposantId);
|
||||
}
|
||||
|
||||
throw new BadRequestException(
|
||||
'Impossible de déterminer la machine associée au composant parent.',
|
||||
);
|
||||
}
|
||||
|
||||
async remove(id: string) {
|
||||
|
||||
Reference in New Issue
Block a user