refactor(machines) : remove TypeMachine skeleton system, simplify machine creation
- Remove TypeEdit*, TypeInfoDisplay, MachineSkeletonSummary, MachineCreatePreview components - Remove machine-skeleton pages and type pages - Remove useMachineTypesApi, useMachineSkeletonEditor, useMachineCreateSelections composables - Add AddEntityToMachineModal for direct entity linking - Update machine detail/create pages for direct custom fields - Fix SearchSelect, category display, and ipartial search filters Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -39,6 +39,8 @@ import {
|
||||
resolveIdentifier,
|
||||
resolveProductReference as _resolveProductReference,
|
||||
getProductDisplay as _getProductDisplay,
|
||||
getProductSuppliersLabel,
|
||||
getProductPriceLabel,
|
||||
extractParentLinkIdentifiers,
|
||||
} from '~/shared/utils/productDisplayUtils'
|
||||
import {
|
||||
@@ -64,7 +66,7 @@ export function useMachineDetailData(machineId: string) {
|
||||
|
||||
const {
|
||||
updateMachine: updateMachineApi,
|
||||
reconfigureSkeleton: reconfigureMachineSkeleton,
|
||||
updateStructure: updateMachineStructure,
|
||||
} = useMachines()
|
||||
const { updateComposant: updateComposantApi } = useComposants()
|
||||
const { updatePiece: updatePieceApi } = usePieces()
|
||||
@@ -75,11 +77,12 @@ export function useMachineDetailData(machineId: string) {
|
||||
upsertCustomFieldValue,
|
||||
updateCustomFieldValue: updateCustomFieldValueApi,
|
||||
} = useCustomFields()
|
||||
const { get } = useApi()
|
||||
const { get, post: apiPost, delete: apiDel } = useApi()
|
||||
const {
|
||||
uploadDocuments,
|
||||
deleteDocument,
|
||||
loadDocumentsByMachine,
|
||||
loadDocumentsByProduct,
|
||||
} = useDocuments()
|
||||
const toast = useToast()
|
||||
const { constructeurs, loadConstructeurs } = useConstructeurs()
|
||||
@@ -105,6 +108,7 @@ export function useMachineDetailData(machineId: string) {
|
||||
const machineComponentLinks = ref<AnyRecord[]>([])
|
||||
const machinePieceLinks = ref<AnyRecord[]>([])
|
||||
const machineProductLinks = ref<AnyRecord[]>([])
|
||||
const productDocumentsMap = ref<Map<string, AnyRecord[]>>(new Map())
|
||||
const printAreaRef = ref<HTMLElement | null>(null)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -169,39 +173,21 @@ export function useMachineDetailData(machineId: string) {
|
||||
const componentsCollapsed = ref(true)
|
||||
const collapseToggleToken = ref(0)
|
||||
|
||||
const piecesCollapsed = ref(true)
|
||||
const pieceCollapseToggleToken = ref(0)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Product helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const machineType = computed(() => (machine.value as AnyRecord)?.typeMachine || null)
|
||||
|
||||
const componentTypeOptions = computed(() => componentTypes.value || [])
|
||||
const pieceTypeOptions = computed(() => pieceTypes.value || [])
|
||||
|
||||
const componentRequirements = computed(
|
||||
() => ((machineType.value as AnyRecord)?.componentRequirements as AnyRecord[]) || [],
|
||||
)
|
||||
const pieceRequirements = computed(
|
||||
() => ((machineType.value as AnyRecord)?.pieceRequirements as AnyRecord[]) || [],
|
||||
)
|
||||
const productRequirements = computed(
|
||||
() => ((machineType.value as AnyRecord)?.productRequirements as AnyRecord[]) || [],
|
||||
)
|
||||
const machineHasSkeletonRequirements = computed(() =>
|
||||
componentRequirements.value.length > 0 ||
|
||||
pieceRequirements.value.length > 0 ||
|
||||
productRequirements.value.length > 0,
|
||||
)
|
||||
|
||||
const componentTypeLabelMap = computed(() => {
|
||||
const map = new Map<string, string>()
|
||||
componentTypeOptions.value.forEach((type) => {
|
||||
if (type?.id) map.set(type.id as string, (type.name as string) || '')
|
||||
})
|
||||
componentRequirements.value.forEach((req: AnyRecord) => {
|
||||
const type = req.typeComposant as AnyRecord | undefined
|
||||
if (type?.id) map.set(type.id as string, (type.name as string) || '')
|
||||
})
|
||||
return map
|
||||
})
|
||||
|
||||
@@ -210,10 +196,6 @@ export function useMachineDetailData(machineId: string) {
|
||||
pieceTypeOptions.value.forEach((type) => {
|
||||
if (type?.id) map.set(type.id as string, (type.name as string) || '')
|
||||
})
|
||||
pieceRequirements.value.forEach((req: AnyRecord) => {
|
||||
const type = req.typePiece as AnyRecord | undefined
|
||||
if (type?.id) map.set(type.id as string, (type.name as string) || '')
|
||||
})
|
||||
return map
|
||||
})
|
||||
|
||||
@@ -310,8 +292,7 @@ export function useMachineDetailData(machineId: string) {
|
||||
|
||||
const transformCustomFields = (piecesData: AnyRecord[]): AnyRecord[] => {
|
||||
return (piecesData || []).map((piece) => {
|
||||
const requirement = (piece.typeMachinePieceRequirement as AnyRecord) || {}
|
||||
const typePiece = (requirement.typePiece as AnyRecord) || (piece.typePiece as AnyRecord) || {}
|
||||
const typePiece = (piece.typePiece as AnyRecord) || {}
|
||||
|
||||
const normalizeStructureDefs = (structure: unknown) =>
|
||||
structure ? normalizeStructureForEditor(structure as AnyRecord) : null
|
||||
@@ -320,10 +301,6 @@ export function useMachineDetailData(machineId: string) {
|
||||
normalizeStructureDefs((piece.definition as AnyRecord)?.structure),
|
||||
normalizeStructureDefs((piece.typePiece as AnyRecord)?.structure),
|
||||
normalizeStructureDefs(typePiece.structure),
|
||||
normalizeStructureDefs(typePiece.pieceSkeleton),
|
||||
normalizeStructureDefs((piece.typePiece as AnyRecord)?.pieceSkeleton),
|
||||
normalizeStructureDefs(requirement.structure),
|
||||
normalizeStructureDefs(requirement.pieceSkeleton),
|
||||
]
|
||||
|
||||
const valueEntries = [
|
||||
@@ -347,17 +324,16 @@ export function useMachineDetailData(machineId: string) {
|
||||
normalizeExistingCustomFieldDefinitions((piece.definition as AnyRecord)?.customFields),
|
||||
normalizeExistingCustomFieldDefinitions((piece.typePiece as AnyRecord)?.customFields),
|
||||
normalizeExistingCustomFieldDefinitions(typePiece.customFields),
|
||||
normalizeExistingCustomFieldDefinitions((requirement.typePiece as AnyRecord)?.customFields),
|
||||
normalizeExistingCustomFieldDefinitions(requirement.customFields),
|
||||
normalizeExistingCustomFieldDefinitions((requirement.definition as AnyRecord)?.customFields),
|
||||
...normalizedStructureDefs.map((def) => getStructureCustomFields(def)),
|
||||
),
|
||||
)
|
||||
|
||||
const constructeurIds = uniqueConstructeurIds(
|
||||
piece.constructeurs,
|
||||
piece.constructeurIds,
|
||||
piece.constructeurId,
|
||||
piece.constructeur,
|
||||
(piece.originalPiece as AnyRecord)?.constructeurs,
|
||||
(piece.originalPiece as AnyRecord)?.constructeurIds,
|
||||
(piece.originalPiece as AnyRecord)?.constructeurId,
|
||||
(piece.originalPiece as AnyRecord)?.constructeur,
|
||||
@@ -396,7 +372,6 @@ export function useMachineDetailData(machineId: string) {
|
||||
constructeurId: constructeurIds[0] || null,
|
||||
typePieceId:
|
||||
piece.typePieceId ||
|
||||
(piece.typeMachinePieceRequirement as AnyRecord)?.typePieceId ||
|
||||
(piece.typePiece as AnyRecord)?.id ||
|
||||
null,
|
||||
__productDisplay: productDisplay,
|
||||
@@ -409,16 +384,12 @@ export function useMachineDetailData(machineId: string) {
|
||||
structure ? normalizeStructureForEditor(structure as AnyRecord) : null
|
||||
|
||||
return (componentsData || []).map((component) => {
|
||||
const requirement = (component.typeMachineComponentRequirement as AnyRecord) || {}
|
||||
const type = (requirement.typeComposant as AnyRecord) || (component.typeComposant as AnyRecord) || {}
|
||||
const type = (component.typeComposant as AnyRecord) || {}
|
||||
|
||||
const normalizedStructureDefs = [
|
||||
normalizeStructureDefs((component.definition as AnyRecord)?.structure),
|
||||
normalizeStructureDefs((component.typeComposant as AnyRecord)?.structure),
|
||||
normalizeStructureDefs(type.structure),
|
||||
normalizeStructureDefs(type.componentSkeleton),
|
||||
normalizeStructureDefs(requirement.structure),
|
||||
normalizeStructureDefs(requirement.componentSkeleton),
|
||||
]
|
||||
|
||||
const actualComponent = (component.originalComposant as AnyRecord) || component
|
||||
@@ -445,9 +416,6 @@ export function useMachineDetailData(machineId: string) {
|
||||
normalizeExistingCustomFieldDefinitions((component.typeComposant as AnyRecord)?.customFields),
|
||||
normalizeExistingCustomFieldDefinitions(type.customFields),
|
||||
normalizeExistingCustomFieldDefinitions(actualComponent?.customFields),
|
||||
normalizeExistingCustomFieldDefinitions((requirement.typeComposant as AnyRecord)?.customFields),
|
||||
normalizeExistingCustomFieldDefinitions(requirement.customFields),
|
||||
normalizeExistingCustomFieldDefinitions((requirement.definition as AnyRecord)?.customFields),
|
||||
...normalizedStructureDefs.map((def) => getStructureCustomFields(def)),
|
||||
),
|
||||
)
|
||||
@@ -464,9 +432,11 @@ export function useMachineDetailData(machineId: string) {
|
||||
: []
|
||||
|
||||
const constructeurIds = uniqueConstructeurIds(
|
||||
component.constructeurs,
|
||||
component.constructeurIds,
|
||||
component.constructeurId,
|
||||
component.constructeur,
|
||||
actualComponent?.constructeurs,
|
||||
actualComponent?.constructeurIds,
|
||||
actualComponent?.constructeurId,
|
||||
actualComponent?.constructeur,
|
||||
@@ -505,7 +475,6 @@ export function useMachineDetailData(machineId: string) {
|
||||
constructeurId: constructeurIds[0] || null,
|
||||
typeComposantId:
|
||||
component.typeComposantId ||
|
||||
(component.typeMachineComponentRequirement as AnyRecord)?.typeComposantId ||
|
||||
(component.typeComposant as AnyRecord)?.id ||
|
||||
null,
|
||||
__productDisplay: productDisplay,
|
||||
@@ -573,6 +542,87 @@ export function useMachineDetailData(machineId: string) {
|
||||
})
|
||||
})
|
||||
|
||||
const machineDirectProducts = computed(() => {
|
||||
return machineProductLinks.value.map((link) => {
|
||||
const productObj = link.product as AnyRecord | string | null
|
||||
let resolved: AnyRecord | null = null
|
||||
let productId: string | null = null
|
||||
|
||||
if (typeof productObj === 'string') {
|
||||
productId = productObj.split('/').pop() || null
|
||||
resolved = productId ? findProductById(productId) : null
|
||||
} else if (productObj && typeof productObj === 'object') {
|
||||
productId = (productObj as AnyRecord)?.id as string | null
|
||||
// Prefer the embedded product from the structure endpoint — it has richer
|
||||
// data (typeProduct as object, supplierPrice, constructeurs) than the
|
||||
// global products cache which may store typeProduct as an IRI string.
|
||||
const cached = productId ? findProductById(productId) : null
|
||||
resolved = productObj as AnyRecord
|
||||
if (cached) {
|
||||
// Merge: use embedded as base, overlay any non-null cached fields
|
||||
resolved = { ...resolved, ...Object.fromEntries(
|
||||
Object.entries(cached as AnyRecord).filter(([, v]) => v != null && v !== ''),
|
||||
) }
|
||||
// But always prefer the embedded typeProduct when it's an object
|
||||
if (productObj.typeProduct && typeof productObj.typeProduct === 'object') {
|
||||
resolved.typeProduct = productObj.typeProduct
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const constructeurIds = uniqueConstructeurIds(
|
||||
resolved?.constructeurs,
|
||||
resolved?.constructeurIds,
|
||||
)
|
||||
const resolvedConstructeurs = resolveConstructeurs(
|
||||
constructeurIds,
|
||||
resolved?.constructeurs as any[] || [],
|
||||
constructeurs.value,
|
||||
)
|
||||
|
||||
return {
|
||||
id: (resolved?.id as string) || productId || null,
|
||||
linkId: (link.id as string) || (typeof link['@id'] === 'string' ? link['@id'].split('/').pop() : null) || null,
|
||||
name: (resolved?.name as string) || 'Produit inconnu',
|
||||
reference: (resolved?.reference as string) || null,
|
||||
supplierLabel: resolvedConstructeurs.length
|
||||
? resolvedConstructeurs.map((c) => c.name).filter(Boolean).join(', ') || null
|
||||
: getProductSuppliersLabel(resolved),
|
||||
priceLabel: resolved ? getProductPriceLabel(resolved) : null,
|
||||
groupLabel: ((resolved?.typeProduct as AnyRecord)?.name as string) || '',
|
||||
documents: productId ? (productDocumentsMap.value.get(productId) || []) : [],
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const loadProductDocuments = async () => {
|
||||
const productIds = machineProductLinks.value
|
||||
.map((link) => {
|
||||
const p = link.product as AnyRecord | string | null
|
||||
if (typeof p === 'string') return p.split('/').pop() || null
|
||||
return (p as AnyRecord)?.id as string | null
|
||||
})
|
||||
.filter((id): id is string => !!id)
|
||||
|
||||
const results = await Promise.allSettled(
|
||||
productIds.map(async (id) => {
|
||||
const result: any = await loadDocumentsByProduct(id, { updateStore: false })
|
||||
if (result.success && Array.isArray(result.data)) {
|
||||
return { id, docs: result.data as AnyRecord[] }
|
||||
}
|
||||
return { id, docs: [] }
|
||||
}),
|
||||
)
|
||||
|
||||
const map = new Map<string, AnyRecord[]>()
|
||||
results.forEach((r) => {
|
||||
if (r.status === 'fulfilled' && r.value.docs.length) {
|
||||
map.set(r.value.id, r.value.docs)
|
||||
}
|
||||
})
|
||||
productDocumentsMap.value = map
|
||||
}
|
||||
|
||||
const machineDocumentsList = computed(
|
||||
() => ((machine.value as AnyRecord)?.documents as AnyRecord[]) || [],
|
||||
)
|
||||
@@ -583,166 +633,6 @@ export function useMachineDetailData(machineId: string) {
|
||||
return fields.filter((field) => shouldDisplayCustomField(field))
|
||||
})
|
||||
|
||||
const componentRequirementGroups = computed(() => {
|
||||
const reqs = ((machine.value as AnyRecord)?.typeMachine as AnyRecord)?.componentRequirements as AnyRecord[] || []
|
||||
if (!reqs.length) return []
|
||||
|
||||
const groups = reqs.map((requirement: AnyRecord) => ({
|
||||
requirement,
|
||||
components: [] as AnyRecord[],
|
||||
}))
|
||||
const map = new Map(groups.map((g) => [g.requirement.id, g]))
|
||||
|
||||
flattenedComponents.value.forEach((component) => {
|
||||
const reqId = component.typeMachineComponentRequirementId as string
|
||||
if (reqId && map.has(reqId)) {
|
||||
map.get(reqId)!.components.push({
|
||||
...component,
|
||||
__productDisplay: getProductDisplay(component),
|
||||
})
|
||||
}
|
||||
})
|
||||
return groups
|
||||
})
|
||||
|
||||
const pieceRequirementGroups = computed(() => {
|
||||
const reqs = ((machine.value as AnyRecord)?.typeMachine as AnyRecord)?.pieceRequirements as AnyRecord[] || []
|
||||
if (!reqs.length) return []
|
||||
|
||||
const groups = reqs.map((requirement: AnyRecord) => ({
|
||||
requirement,
|
||||
pieces: [] as AnyRecord[],
|
||||
}))
|
||||
const map = new Map(groups.map((g) => [g.requirement.id, g]))
|
||||
|
||||
const collectPieces = (): AnyRecord[] => {
|
||||
const collected: AnyRecord[] = []
|
||||
machinePieces.value.forEach((piece) => {
|
||||
collected.push({
|
||||
...piece,
|
||||
constructeurs: piece.constructeurs || [],
|
||||
parentComponentName: null,
|
||||
__productDisplay: getProductDisplay(piece),
|
||||
})
|
||||
})
|
||||
flattenedComponents.value.forEach((component) => {
|
||||
if (Array.isArray(component.pieces) && (component.pieces as AnyRecord[]).length) {
|
||||
;(component.pieces as AnyRecord[]).forEach((piece) => {
|
||||
collected.push({
|
||||
...piece,
|
||||
constructeurs: piece.constructeurs || [],
|
||||
parentComponentName: component.name,
|
||||
__productDisplay: getProductDisplay(piece),
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
return collected
|
||||
}
|
||||
|
||||
collectPieces().forEach((piece) => {
|
||||
const reqId = piece.typeMachinePieceRequirementId as string
|
||||
if (reqId && map.has(reqId)) {
|
||||
map.get(reqId)!.pieces.push(piece)
|
||||
}
|
||||
})
|
||||
return groups
|
||||
})
|
||||
|
||||
const productRequirementGroups = computed(() => {
|
||||
const reqs = ((machine.value as AnyRecord)?.typeMachine as AnyRecord)?.productRequirements as AnyRecord[] || []
|
||||
if (!reqs.length) return []
|
||||
|
||||
const componentAggregates = flattenedComponents.value || []
|
||||
const pieceAggregates = collectPiecesForSkeleton()
|
||||
const links = Array.isArray(machineProductLinks.value) ? machineProductLinks.value : []
|
||||
|
||||
return reqs.map((requirement: AnyRecord) => {
|
||||
const typeProductId =
|
||||
(requirement.typeProductId as string) ||
|
||||
(requirement.typeProduct as AnyRecord)?.id as string ||
|
||||
null
|
||||
|
||||
const directProducts = links
|
||||
.filter((link) => {
|
||||
const requirementId = resolveIdentifier(
|
||||
link?.typeMachineProductRequirementId,
|
||||
link?.requirementId,
|
||||
)
|
||||
return requirementId === requirement.id
|
||||
})
|
||||
.map((link) => {
|
||||
const productId = resolveIdentifier(link?.productId, (link?.product as AnyRecord)?.id)
|
||||
const product =
|
||||
productId ? findProductById(productId as string) : (link?.product as AnyRecord) ?? null
|
||||
|
||||
const supplierLabel = Array.isArray((product as AnyRecord)?.constructeurs)
|
||||
? ((product as AnyRecord).constructeurs as AnyRecord[])
|
||||
.map((c) => c?.name)
|
||||
.filter(Boolean)
|
||||
.join(', ')
|
||||
: (link?.constructeursLabel as string) || null
|
||||
|
||||
const priceValue =
|
||||
(product as AnyRecord)?.supplierPrice ?? link?.supplierPrice ?? null
|
||||
|
||||
let priceLabel: string | null = null
|
||||
if (priceValue !== undefined && priceValue !== null) {
|
||||
const numericPrice = Number(priceValue)
|
||||
if (!Number.isNaN(numericPrice)) {
|
||||
priceLabel = `${numericPrice.toFixed(2)} €`
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
id: productId || link?.id || null,
|
||||
name: (product as AnyRecord)?.name || link?.productName || productId || 'Produit',
|
||||
reference: (product as AnyRecord)?.reference || link?.reference || null,
|
||||
supplierLabel,
|
||||
priceLabel,
|
||||
}
|
||||
})
|
||||
|
||||
let componentCount = 0
|
||||
componentAggregates.forEach((component) => {
|
||||
const componentTypeProductId =
|
||||
(component?.product as AnyRecord)?.typeProductId ||
|
||||
((component?.product as AnyRecord)?.typeProduct as AnyRecord)?.id ||
|
||||
null
|
||||
if (typeProductId && componentTypeProductId === typeProductId) componentCount += 1
|
||||
})
|
||||
|
||||
let pieceCount = 0
|
||||
pieceAggregates.forEach((piece) => {
|
||||
const pieceTypeProductId =
|
||||
(piece?.product as AnyRecord)?.typeProductId ||
|
||||
((piece?.product as AnyRecord)?.typeProduct as AnyRecord)?.id ||
|
||||
null
|
||||
if (typeProductId && pieceTypeProductId === typeProductId) pieceCount += 1
|
||||
})
|
||||
|
||||
return {
|
||||
requirement,
|
||||
directProducts,
|
||||
componentCount,
|
||||
pieceCount,
|
||||
totalCount: directProducts.length + componentCount + pieceCount,
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
const machineDirectProducts = computed(() => {
|
||||
return productRequirementGroups.value.flatMap((group: AnyRecord) =>
|
||||
((group.directProducts as AnyRecord[]) || []).map((product) => ({
|
||||
...product,
|
||||
groupLabel:
|
||||
(group.requirement as AnyRecord).label ||
|
||||
((group.requirement as AnyRecord).typeProduct as AnyRecord)?.name ||
|
||||
'Produit requis',
|
||||
})),
|
||||
)
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Machine field methods
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -784,9 +674,6 @@ export function useMachineDetailData(machineId: string) {
|
||||
mergeCustomFieldValuesWithDefinitions(
|
||||
valueEntries,
|
||||
normalizeExistingCustomFieldDefinitions(machine.value.customFields),
|
||||
normalizeExistingCustomFieldDefinitions(
|
||||
(machine.value.typeMachine as AnyRecord)?.customFields,
|
||||
),
|
||||
),
|
||||
).map((field: AnyRecord) => ({ ...field, readOnly: false }))
|
||||
machineCustomFields.value = merged
|
||||
@@ -977,6 +864,7 @@ export function useMachineDetailData(machineId: string) {
|
||||
machine.value.componentLinks = machineComponentLinks.value
|
||||
machine.value.pieceLinks = machinePieceLinks.value
|
||||
}
|
||||
loadProductDocuments().catch(() => {})
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -1126,6 +1014,11 @@ export function useMachineDetailData(machineId: string) {
|
||||
collapseToggleToken.value += 1
|
||||
}
|
||||
|
||||
const toggleAllPieces = () => {
|
||||
piecesCollapsed.value = !piecesCollapsed.value
|
||||
pieceCollapseToggleToken.value += 1
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Print wrappers
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -1146,16 +1039,118 @@ export function useMachineDetailData(machineId: string) {
|
||||
)
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Piece aggregation (used by skeleton & product requirement groups)
|
||||
// Structure link management
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const collectPiecesForSkeleton = (): AnyRecord[] => {
|
||||
const aggregated: AnyRecord[] = []
|
||||
machinePieces.value.forEach((piece) => aggregated.push(piece))
|
||||
flattenedComponents.value.forEach((component) => {
|
||||
;((component.pieces as AnyRecord[]) || []).forEach((piece) => aggregated.push(piece))
|
||||
const reloadMachineStructure = async () => {
|
||||
const result: any = await get(`/machines/${machineId}/structure`)
|
||||
if (result.success) {
|
||||
const machinePayload =
|
||||
result.data?.machine && typeof result.data.machine === 'object'
|
||||
? result.data.machine
|
||||
: result.data
|
||||
if (machinePayload && typeof machinePayload === 'object') {
|
||||
machine.value = {
|
||||
...machine.value,
|
||||
...machinePayload,
|
||||
documents: machinePayload.documents || (machine.value as AnyRecord)?.documents || [],
|
||||
customFieldValues: machinePayload.customFieldValues || (machine.value as AnyRecord)?.customFieldValues || [],
|
||||
}
|
||||
const linksApplied = applyMachineLinks(result.data)
|
||||
if (linksApplied && machine.value) {
|
||||
machine.value.componentLinks = machineComponentLinks.value
|
||||
machine.value.pieceLinks = machinePieceLinks.value
|
||||
machine.value.productLinks = machineProductLinks.value
|
||||
}
|
||||
syncMachineCustomFields()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const addComponentLink = async (composantId: string) => {
|
||||
const result: any = await apiPost('/machine_component_links', {
|
||||
machine: `/api/machines/${machineId}`,
|
||||
composant: `/api/composants/${composantId}`,
|
||||
})
|
||||
return aggregated
|
||||
if (result.success) {
|
||||
toast.showSuccess('Composant ajouté à la machine')
|
||||
await reloadMachineStructure()
|
||||
} else {
|
||||
toast.showError('Erreur lors de l\'ajout du composant')
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const removeComponentLink = async (linkId: string) => {
|
||||
const result: any = await apiDel(`/machine_component_links/${linkId}`)
|
||||
if (result.success) {
|
||||
toast.showSuccess('Composant retiré de la machine')
|
||||
await reloadMachineStructure()
|
||||
} else {
|
||||
toast.showError('Erreur lors de la suppression du composant')
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const addPieceLink = async (pieceId: string, parentComponentLinkId?: string) => {
|
||||
const payload: any = {
|
||||
machine: `/api/machines/${machineId}`,
|
||||
piece: `/api/pieces/${pieceId}`,
|
||||
}
|
||||
if (parentComponentLinkId) {
|
||||
payload.parentLink = `/api/machine_component_links/${parentComponentLinkId}`
|
||||
}
|
||||
const result: any = await apiPost('/machine_piece_links', payload)
|
||||
if (result.success) {
|
||||
toast.showSuccess('Pièce ajoutée à la machine')
|
||||
await reloadMachineStructure()
|
||||
} else {
|
||||
toast.showError('Erreur lors de l\'ajout de la pièce')
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const removePieceLink = async (linkId: string) => {
|
||||
const result: any = await apiDel(`/machine_piece_links/${linkId}`)
|
||||
if (result.success) {
|
||||
toast.showSuccess('Pièce retirée de la machine')
|
||||
await reloadMachineStructure()
|
||||
} else {
|
||||
toast.showError('Erreur lors de la suppression de la pièce')
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const addProductLink = async (productId: string, parentComponentLinkId?: string, parentPieceLinkId?: string) => {
|
||||
const payload: any = {
|
||||
machine: `/api/machines/${machineId}`,
|
||||
product: `/api/products/${productId}`,
|
||||
}
|
||||
if (parentComponentLinkId) {
|
||||
payload.parentComponentLink = `/api/machine_component_links/${parentComponentLinkId}`
|
||||
}
|
||||
if (parentPieceLinkId) {
|
||||
payload.parentPieceLink = `/api/machine_piece_links/${parentPieceLinkId}`
|
||||
}
|
||||
const result: any = await apiPost('/machine_product_links', payload)
|
||||
if (result.success) {
|
||||
toast.showSuccess('Produit ajouté à la machine')
|
||||
await reloadMachineStructure()
|
||||
} else {
|
||||
toast.showError('Erreur lors de l\'ajout du produit')
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const removeProductLink = async (linkId: string) => {
|
||||
const result: any = await apiDel(`/machine_product_links/${linkId}`)
|
||||
if (result.success) {
|
||||
toast.showSuccess('Produit retiré de la machine')
|
||||
await reloadMachineStructure()
|
||||
} else {
|
||||
toast.showError('Erreur lors de la suppression du produit')
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -1165,7 +1160,7 @@ export function useMachineDetailData(machineId: string) {
|
||||
const loadMachineData = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const machineResult: any = await get(`/machines/${machineId}/skeleton`)
|
||||
const machineResult: any = await get(`/machines/${machineId}/structure`)
|
||||
|
||||
if (!machineResult.success) {
|
||||
console.error('Machine non trouvée:', machineId, machineResult.error)
|
||||
@@ -1233,6 +1228,9 @@ export function useMachineDetailData(machineId: string) {
|
||||
|
||||
collapseAllComponents()
|
||||
|
||||
// Load product documents in background
|
||||
loadProductDocuments().catch(() => {})
|
||||
|
||||
// Wait for documents if still loading
|
||||
await documentPromise
|
||||
} catch (error) {
|
||||
@@ -1256,7 +1254,6 @@ export function useMachineDetailData(machineId: string) {
|
||||
|
||||
watch(() => (machine.value as AnyRecord)?.customFieldValues, () => syncMachineCustomFields(), { deep: true })
|
||||
watch(() => (machine.value as AnyRecord)?.customFields, () => syncMachineCustomFields(), { deep: true })
|
||||
watch(() => ((machine.value as AnyRecord)?.typeMachine as AnyRecord)?.customFields, () => syncMachineCustomFields(), { deep: true })
|
||||
watch(
|
||||
() => [components.value.length, machinePieces.value.length],
|
||||
() => ensurePrintSelectionEntries(),
|
||||
@@ -1298,13 +1295,10 @@ export function useMachineDetailData(machineId: string) {
|
||||
debug,
|
||||
componentsCollapsed,
|
||||
collapseToggleToken,
|
||||
piecesCollapsed,
|
||||
pieceCollapseToggleToken,
|
||||
|
||||
// Computed
|
||||
machineType,
|
||||
componentRequirements,
|
||||
pieceRequirements,
|
||||
productRequirements,
|
||||
machineHasSkeletonRequirements,
|
||||
componentTypeOptions,
|
||||
pieceTypeOptions,
|
||||
componentTypeLabelMap,
|
||||
@@ -1313,12 +1307,9 @@ export function useMachineDetailData(machineId: string) {
|
||||
productById,
|
||||
flattenedComponents,
|
||||
machinePieces,
|
||||
machineDirectProducts,
|
||||
machineDocumentsList,
|
||||
visibleMachineCustomFields,
|
||||
componentRequirementGroups,
|
||||
pieceRequirementGroups,
|
||||
productRequirementGroups,
|
||||
machineDirectProducts,
|
||||
|
||||
// Product helpers
|
||||
findProductById,
|
||||
@@ -1331,7 +1322,6 @@ export function useMachineDetailData(machineId: string) {
|
||||
findComponentById,
|
||||
findPieceById,
|
||||
collectConstructeurs,
|
||||
collectPiecesForSkeleton,
|
||||
|
||||
// Transform
|
||||
transformCustomFields,
|
||||
@@ -1370,6 +1360,7 @@ export function useMachineDetailData(machineId: string) {
|
||||
toggleEditMode,
|
||||
toggleAllComponents,
|
||||
collapseAllComponents,
|
||||
toggleAllPieces,
|
||||
|
||||
// Print
|
||||
printModalOpen,
|
||||
@@ -1384,10 +1375,19 @@ export function useMachineDetailData(machineId: string) {
|
||||
loadMachineData,
|
||||
loadInitialData,
|
||||
|
||||
// External (needed by skeleton editor)
|
||||
// Structure link management
|
||||
addComponentLink,
|
||||
removeComponentLink,
|
||||
addPieceLink,
|
||||
removePieceLink,
|
||||
addProductLink,
|
||||
removeProductLink,
|
||||
reloadMachineStructure,
|
||||
|
||||
// External
|
||||
constructeurs,
|
||||
loadProducts,
|
||||
reconfigureMachineSkeleton,
|
||||
updateMachineStructure,
|
||||
toast,
|
||||
|
||||
// Re-exports for template
|
||||
|
||||
Reference in New Issue
Block a user