feat: gérer les constructeurs multiples

This commit is contained in:
Matthieu
2025-10-28 16:37:10 +01:00
parent da447e4ea2
commit b752fba69a
14 changed files with 901 additions and 222 deletions

View File

@@ -0,0 +1,115 @@
export interface ConstructeurSummary {
id: string;
name?: string | null;
email?: string | null;
phone?: string | null;
}
const isObject = (value: unknown): value is Record<string, unknown> =>
Boolean(value) && typeof value === 'object' && !Array.isArray(value);
const toStringId = (value: unknown): string | null => {
if (typeof value !== 'string') {
return null;
}
const trimmed = value.trim();
return trimmed.length > 0 ? trimmed : null;
};
export const uniqueConstructeurIds = (...sources: unknown[]): string[] => {
const ids = new Set<string>();
const pushId = (value: unknown) => {
const id = toStringId(value);
if (id) {
ids.add(id);
}
};
const explore = (value: unknown): void => {
if (!value) {
return;
}
if (Array.isArray(value)) {
value.forEach(explore);
return;
}
if (typeof value === 'string') {
pushId(value);
return;
}
if (isObject(value)) {
if (Array.isArray(value.constructeurIds)) {
value.constructeurIds.forEach(pushId);
}
if (value.constructeurId) {
pushId(value.constructeurId);
}
if (Array.isArray(value.constructeurs)) {
value.constructeurs.forEach(explore);
}
if (value.constructeur) {
explore(value.constructeur);
}
if (typeof value.id === 'string') {
pushId(value.id);
}
return;
}
};
sources.forEach(explore);
return Array.from(ids);
};
export const resolveConstructeurs = (
ids: string[],
...candidatePools: Array<ConstructeurSummary[] | null | undefined>
): ConstructeurSummary[] => {
if (!Array.isArray(ids) || ids.length === 0) {
return [];
}
const index = new Map<string, ConstructeurSummary>();
const register = (pool?: ConstructeurSummary[] | null) => {
if (!Array.isArray(pool)) {
return;
}
pool.forEach((entry) => {
if (entry && typeof entry === 'object' && typeof entry.id === 'string') {
index.set(entry.id, entry);
}
});
};
candidatePools.forEach(register);
return ids
.map((id) => index.get(id))
.filter((item): item is ConstructeurSummary => Boolean(item))
.map((item) => ({ ...item }));
};
export const formatConstructeurContact = (
constructeur?: ConstructeurSummary | null,
): string =>
[constructeur?.email, constructeur?.phone].filter(Boolean).join(' • ');
export const buildConstructeurRequestPayload = <T extends Record<string, any>>(
payload: T,
): T & { constructeurIds: string[] } => {
const ids = uniqueConstructeurIds(
payload?.constructeurIds,
payload?.constructeurId,
payload?.constructeur,
payload?.constructeurs,
);
const next = { ...payload } as Record<string, any>;
next.constructeurIds = ids;
delete next.constructeurId;
delete next.constructeur;
delete next.constructeurs;
return next as T & { constructeurIds: string[] };
};

View File

@@ -11,6 +11,7 @@ import {
type PieceModelStructureForEditor,
createEmptyPieceModelStructure,
} from './types/inventory'
import { uniqueConstructeurIds } from './constructeurUtils'
export const isPlainObject = (value: unknown): value is Record<string, unknown> => {
return value !== null && typeof value === 'object' && !Array.isArray(value)
@@ -686,7 +687,7 @@ export const formatStructurePreview = (structure: any) => {
export interface DefinitionOverridePayload {
name?: string
reference?: string
constructeurId?: string | null
constructeurIds?: string[]
prix?: number
}
@@ -711,8 +712,14 @@ export const sanitizeDefinitionOverrides = (definition: any): DefinitionOverride
}
}
if (definition.constructeurId !== undefined && definition.constructeurId !== null && definition.constructeurId !== '') {
payload.constructeurId = definition.constructeurId
const constructeurIds = uniqueConstructeurIds(
definition.constructeurIds,
definition.constructeurId,
definition.constructeur,
definition.constructeurs,
)
if (constructeurIds.length) {
payload.constructeurIds = constructeurIds
}
if (definition.prix !== undefined && definition.prix !== null && definition.prix !== '') {