refactor: prepare multi-machine inventory associations

This commit is contained in:
Matthieu
2025-10-08 16:23:49 +02:00
parent c23ba3a587
commit 48a74b74d7
19 changed files with 1166 additions and 297 deletions

View File

@@ -20,10 +20,9 @@ type ComponentRequirementWithType =
Prisma.TypeMachineComponentRequirementGetPayload<{
include: { typeComposant: true };
}>;
type PieceRequirementWithType =
Prisma.TypeMachinePieceRequirementGetPayload<{
include: { typePiece: true };
}>;
type PieceRequirementWithType = Prisma.TypeMachinePieceRequirementGetPayload<{
include: { typePiece: true };
}>;
type ModelTypeWithSkeleton = ComponentRequirementWithType['typeComposant'];
type PieceTypeWithSkeleton = PieceRequirementWithType['typePiece'];
@@ -65,112 +64,137 @@ export class ComposantsService {
}
async create(createComposantDto: CreateComposantDto) {
const requirementId = createComposantDto.typeMachineComponentRequirementId;
const requirementId =
createComposantDto.typeMachineComponentRequirementId ?? null;
let machineId = createComposantDto.machineId;
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 && machineId !== parentMachineId) {
if (machineId && parentMachineId && machineId !== parentMachineId) {
throw new BadRequestException(
'Le composant parent ne correspond pas à la machine ciblée.',
);
}
machineId = parentMachineId;
machineId = parentMachineId ?? machineId;
}
if (!machineId) {
throw new BadRequestException(
'Un machineId ou un parentComposantId valide est requis pour créer un composant.',
);
}
let requirement: ComponentRequirementWithType | null = null;
let componentRequirements: ComponentRequirementWithType[] = [];
let pieceRequirements: PieceRequirementWithType[] = [];
const machine = await this.prisma.machine.findUnique({
where: { id: machineId },
include: {
typeMachine: {
include: {
componentRequirements: {
include: {
typeComposant: true,
if (machineId) {
const machine = await this.prisma.machine.findUnique({
where: { id: machineId },
include: {
typeMachine: {
include: {
componentRequirements: {
include: {
typeComposant: true,
},
},
},
pieceRequirements: {
include: {
typePiece: 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.',
);
}
if (!machine || !machine.typeMachine) {
throw new BadRequestException(
'La machine ciblée doit être associée à un type de machine pour valider les requirements.',
);
}
const componentRequirements =
(machine.typeMachine.componentRequirements as ComponentRequirementWithType[]) ?? [];
const pieceRequirements =
(machine.typeMachine.pieceRequirements as PieceRequirementWithType[]) ?? [];
componentRequirements =
(machine.typeMachine
.componentRequirements as ComponentRequirementWithType[]) ?? [];
pieceRequirements =
(machine.typeMachine.pieceRequirements as PieceRequirementWithType[]) ??
[];
const requirement = componentRequirements.find(
(componentRequirement) => componentRequirement.id === requirementId,
);
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 (!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.',
);
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;
createComposantDto.typeComposantId ??
requirement?.typeComposantId ??
null;
const created = await this.prisma.composant.create({
data: {
...createComposantDto,
machineId,
typeComposantId,
},
include: COMPONENT_WITH_RELATIONS_INCLUDE,
});
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,
const data: Prisma.ComposantUncheckedCreateInput = {
name: createComposantDto.name,
reference: createComposantDto.reference ?? null,
constructeurId: createComposantDto.constructeurId ?? null,
prix:
createComposantDto.prix !== undefined ? createComposantDto.prix : null,
machineId,
componentRequirements,
pieceRequirements,
componentRequirementUsage,
pieceRequirementUsage,
});
parentComposantId: createComposantDto.parentComposantId ?? null,
typeComposantId,
typeMachineComponentRequirementId:
requirement?.id ?? requirementId ?? null,
};
const created = (await this.prisma.composant.create({
data,
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 as ComposantWithRelations | null) ?? (created as ComposantWithRelations);
return component ?? created;
}
async findAll() {
@@ -225,8 +249,8 @@ export class ComposantsService {
pieceRequirementUsage: Map<string, number>;
}) {
const skeleton = this.parseComponentSkeleton(
(componentType as { componentSkeleton?: Prisma.JsonValue | null } | null)?.
componentSkeleton,
(componentType as { componentSkeleton?: Prisma.JsonValue | null } | null)
?.componentSkeleton,
);
if (!skeleton) {
return;
@@ -274,15 +298,12 @@ export class ComposantsService {
},
});
this.incrementRequirementUsage(
componentRequirementUsage,
requirement.id,
);
this.incrementRequirementUsage(componentRequirementUsage, requirement.id);
await this.populateComponentFromSkeleton({
componentId: createdChild.id,
componentName: createdChild.name,
componentType: requirement.typeComposant as ModelTypeWithSkeleton,
componentType: requirement.typeComposant,
machineId,
componentRequirements,
pieceRequirements,
@@ -311,7 +332,11 @@ export class ComposantsService {
typeComposantId: string | null,
customFields: ComponentModelStructure['customFields'],
) {
if (!typeComposantId || !Array.isArray(customFields) || customFields.length === 0) {
if (
!typeComposantId ||
!Array.isArray(customFields) ||
customFields.length === 0
) {
return;
}
@@ -324,12 +349,16 @@ export class ComposantsService {
return;
}
const definitionMap = new Map(definitions.map((field) => [field.name, field.id]));
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));
const existingIds = new Set(
existingValues.map((value) => value.customFieldId),
);
for (const field of customFields) {
const key = this.normalizeIdentifier(field?.key);
@@ -384,7 +413,11 @@ export class ComposantsService {
continue;
}
const name = this.buildPieceName(entry, requirement.typePiece, componentName);
const name = this.buildPieceName(
entry,
requirement.typePiece,
componentName,
);
await this.prisma.piece.create({
data: {
@@ -418,7 +451,9 @@ export class ComposantsService {
}
if (familyCode && requirement.typeComposant?.code) {
return this.normalizeCode(requirement.typeComposant.code) === familyCode;
return (
this.normalizeCode(requirement.typeComposant.code) === familyCode
);
}
return false;
@@ -516,7 +551,9 @@ export class ComposantsService {
typeComposant: ModelTypeWithSkeleton | null,
parentName?: string,
): string {
const alias = this.normalizeIdentifier((subcomponent as { alias?: string }).alias);
const alias = this.normalizeIdentifier(
(subcomponent as { alias?: string }).alias,
);
if (alias) {
return alias;
}