feat: centralize constructeur link synchronization

This commit is contained in:
Matthieu
2025-10-30 11:32:34 +01:00
parent fe471b9e81
commit d05b91d7cd
6 changed files with 713 additions and 89 deletions

View File

@@ -109,6 +109,15 @@ type PieceRecord = {
updatedAt: Date;
};
type ConstructeurRecord = {
id: string;
name: string;
email: Nullable<string>;
phone: Nullable<string>;
createdAt: Date;
updatedAt: Date;
};
type MachineComponentLinkRecord = {
id: string;
machineId: string;
@@ -202,6 +211,15 @@ class InMemoryPrismaService {
private customFields: CustomFieldRecord[] = [];
private customFieldValues: CustomFieldValueRecord[] = [];
private profiles: ProfileRecord[] = [];
private constructeurs: ConstructeurRecord[] = [];
private readonly constructeurLinkOrientation: Record<
string,
{ parentColumn: 'A' | 'B'; constructeurColumn: 'A' | 'B' }
> = {
_MachineConstructeurs: { parentColumn: 'A', constructeurColumn: 'B' },
_ComposantConstructeurs: { parentColumn: 'A', constructeurColumn: 'B' },
_PieceConstructeurs: { parentColumn: 'A', constructeurColumn: 'B' },
};
async onModuleInit() {}
async onModuleDestroy() {}
@@ -229,6 +247,7 @@ class InMemoryPrismaService {
this.customFields = [];
this.customFieldValues = [];
this.profiles = [];
this.constructeurs = [];
}
private readonly modelTypeDelegate = {
@@ -984,6 +1003,120 @@ class InMemoryPrismaService {
},
};
constructeur = {
findMany: async ({ where, select, orderBy }: any = {}) => {
let records = [...this.constructeurs];
if (where?.id?.in) {
const ids = Array.isArray(where.id.in) ? where.id.in : [];
records = records.filter((item) => ids.includes(item.id));
}
if (where?.OR && Array.isArray(where.OR)) {
const termCandidate = where.OR.find(
(clause: any) => clause?.name?.contains,
);
const term =
termCandidate?.name?.contains ??
termCandidate?.email?.contains ??
termCandidate?.phone?.contains ??
'';
const normalized = term.toLowerCase().trim();
if (normalized) {
records = records.filter((record) => {
const nameMatch = record.name.toLowerCase().includes(normalized);
const emailMatch =
record.email?.toLowerCase().includes(normalized) ?? false;
const phoneMatch =
record.phone?.toLowerCase().includes(normalized) ?? false;
return nameMatch || emailMatch || phoneMatch;
});
}
}
if (orderBy?.name) {
records = [...records].sort((a, b) =>
orderBy.name === 'desc'
? b.name.localeCompare(a.name)
: a.name.localeCompare(b.name),
);
}
return records.map((record) => this.applySelect(record, select));
},
findUnique: async ({ where, select }: any) => {
const record = this.constructeurs.find((item) => item.id === where?.id);
return record ? this.applySelect(record, select) : null;
},
findFirst: async ({ where, select }: any = {}) => {
if (where?.name?.equals) {
const target = where.name.equals.toLowerCase();
const record = this.constructeurs.find(
(item) => item.name.toLowerCase() === target,
);
return record ? this.applySelect(record, select) : null;
}
return null;
},
create: async ({ data, select }: any) => {
const now = new Date();
const record: ConstructeurRecord = {
id: data.id ?? generateId('constructeur'),
name: data.name?.trim?.() ?? '',
email: data.email?.trim?.() ?? null,
phone: data.phone?.trim?.() ?? null,
createdAt: now,
updatedAt: now,
};
this.constructeurs.push(record);
return this.applySelect(record, select);
},
update: async ({ where, data, select }: any) => {
const record = this.constructeurs.find((item) => item.id === where?.id);
if (!record) {
throw new Error('Constructeur not found');
}
if (data.name !== undefined) {
record.name =
this.applyUpdateValue<string>(data.name)?.trim?.() ?? record.name;
}
if (data.email !== undefined) {
record.email =
this.applyUpdateValue<string | null>(data.email)?.trim?.() ?? null;
}
if (data.phone !== undefined) {
record.phone =
this.applyUpdateValue<string | null>(data.phone)?.trim?.() ?? null;
}
record.updatedAt = new Date();
return this.applySelect(record, select);
},
delete: async ({ where, select }: any) => {
const index = this.constructeurs.findIndex(
(item) => item.id === where?.id,
);
if (index === -1) {
throw new Error('Constructeur not found');
}
const [deleted] = this.constructeurs.splice(index, 1);
return this.applySelect(deleted, select);
},
};
async __getConstructeurLinkOrientation(table: string) {
return (
this.constructeurLinkOrientation[table] ?? {
parentColumn: 'A',
constructeurColumn: 'B',
}
);
}
profile = {
count: async ({ where }: any) => {
return this.profiles.filter((profile) => {
@@ -1315,6 +1448,40 @@ class InMemoryPrismaService {
.map((item) => ({ ...item }));
}
async __syncConstructeurLinks(
table: string,
parentId: string,
ids: string[],
): Promise<void> {
const filtered = ids.filter((id) =>
this.constructeurs.some((item) => item.id === id),
);
switch (table) {
case '_MachineConstructeurs':
this.assignConstructeurs(this.machines, parentId, filtered);
break;
case '_ComposantConstructeurs':
this.assignConstructeurs(this.composants, parentId, filtered);
break;
case '_PieceConstructeurs':
this.assignConstructeurs(this.pieces, parentId, filtered);
break;
default:
throw new Error(`Unsupported constructeur link table: ${table}`);
}
}
private assignConstructeurs<
T extends { id: string; constructeurIds: string[] },
>(collection: T[], parentId: string, ids: string[]) {
const record = collection.find((item) => item.id === parentId);
if (!record) {
return;
}
record.constructeurIds = [...ids];
}
private buildMachine(machine: MachineRecord, include: any) {
const base: any = { ...machine };