From e0f761da2b0660a21f862b954eff212022c417ac Mon Sep 17 00:00:00 2001 From: Matthieu Date: Tue, 31 Mar 2026 17:02:32 +0200 Subject: [PATCH] feat(constructeur) : update product edit flow with supplier references Co-Authored-By: Claude Opus 4.6 (1M context) --- app/composables/useProducts.ts | 8 +++-- app/pages/product/[id]/edit.vue | 56 +++++++++++++++++++++++------- app/pages/product/[id]/index.vue | 59 ++++++++++++++++++++++++++------ app/pages/product/create.vue | 38 ++++++++++++++++++-- 4 files changed, 131 insertions(+), 30 deletions(-) diff --git a/app/composables/useProducts.ts b/app/composables/useProducts.ts index 98364ce..e63a1df 100644 --- a/app/composables/useProducts.ts +++ b/app/composables/useProducts.ts @@ -2,7 +2,7 @@ import { ref } from 'vue' import { useToast } from './useToast' import { useApi } from './useApi' import { humanizeError } from '~/shared/utils/errorMessages' -import { buildConstructeurRequestPayload, uniqueConstructeurIds } from '~/shared/constructeurUtils' +import { uniqueConstructeurIds } from '~/shared/constructeurUtils' import { useConstructeurs, type Constructeur } from './useConstructeurs' import { extractRelationId, normalizeRelationIds } from '~/shared/apiRelations' import { extractCollection } from '~/shared/utils/apiHelpers' @@ -196,7 +196,8 @@ export function useProducts() { } const createProduct = async (payload: Partial): Promise => { - const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(payload)) + const { constructeurIds, constructeurs, constructeurId, constructeur, ...cleanPayload } = payload as any + const normalizedPayload = normalizeRelationIds(cleanPayload) loading.value = true error.value = null try { @@ -225,7 +226,8 @@ export function useProducts() { } const updateProduct = async (id: string, payload: Partial): Promise => { - const normalizedPayload = normalizeRelationIds(buildConstructeurRequestPayload(payload)) + const { constructeurIds, constructeurs, constructeurId, constructeur, ...cleanPayload } = payload as any + const normalizedPayload = normalizeRelationIds(cleanPayload) loading.value = true error.value = null try { diff --git a/app/pages/product/[id]/edit.vue b/app/pages/product/[id]/edit.vue index acb9404..4000c6c 100644 --- a/app/pages/product/[id]/edit.vue +++ b/app/pages/product/[id]/edit.vue @@ -105,6 +105,11 @@ + +
+ + + +
@@ -303,10 +314,12 @@ import { useToast } from '~/composables/useToast' import { humanizeError } from '~/shared/utils/errorMessages' import { useDocuments } from '~/composables/useDocuments' import { useConstructeurs } from '~/composables/useConstructeurs' +import { useConstructeurLinks } from '~/composables/useConstructeurLinks' import { useProductHistory } from '~/composables/useProductHistory' import { usePermissions } from '~/composables/usePermissions' import { formatProductStructurePreview, normalizeProductStructureForSave } from '~/shared/modelUtils' -import { uniqueConstructeurIds } from '~/shared/constructeurUtils' +import { constructeurIdsFromLinks } from '~/shared/constructeurUtils' +import type { ConstructeurLinkEntry } from '~/shared/constructeurUtils' import { getModelType } from '~/services/modelTypes' import type { ProductModelStructure } from '~/shared/types/inventory' import { canPreviewDocument } from '~/utils/documentPreview' @@ -330,6 +343,7 @@ const { updateDocument, } = useDocuments() const { ensureConstructeurs, getConstructeurById } = useConstructeurs() +const { fetchLinks, syncLinks } = useConstructeurLinks() const { history, loading: historyLoading, @@ -339,6 +353,9 @@ const { const isEditMode = ref(false) +const constructeurLinks = ref([]) +const originalConstructeurLinks = ref([]) + const product = ref(null) const productType = ref(null) const structure = ref(null) @@ -529,17 +546,19 @@ const hydrateForm = () => { } editionForm.name = product.value.name || '' editionForm.reference = product.value.reference || '' - editionForm.constructeurIds = uniqueConstructeurIds( - product.value, - Array.isArray(product.value.constructeurs) ? product.value.constructeurs : [], - ) + // Load constructeur links + fetchLinks('product', String(route.params.id)).then((links) => { + constructeurLinks.value = links + originalConstructeurLinks.value = links.map(l => ({ ...l })) + editionForm.constructeurIds = constructeurIdsFromLinks(links) + if (editionForm.constructeurIds.length) { + void ensureConstructeurs(editionForm.constructeurIds) + } + }) editionForm.supplierPrice = product.value.supplierPrice !== null && product.value.supplierPrice !== undefined ? String(product.value.supplierPrice) : '' refreshCustomFieldInputs(structure.value, product.value.customFieldValues) - if (editionForm.constructeurIds.length) { - ensureConstructeurs(editionForm.constructeurIds).catch(() => {}) - } } watch( @@ -557,12 +576,9 @@ const submitEdition = async () => { return } - const constructeurIds = uniqueConstructeurIds(editionForm.constructeurIds) - const payload: Record = { name: editionForm.name.trim(), reference: editionForm.reference.trim() || null, - constructeurIds, } const rawPrice = typeof editionForm.supplierPrice === 'string' @@ -589,6 +605,8 @@ const submitEdition = async () => { toast.showError(`Impossible d'enregistrer ${failedFields.length} champ(s): ${failedFields.join(', ')}`) return } + await syncLinks('product', product.value.id, originalConstructeurLinks.value, constructeurLinks.value) + originalConstructeurLinks.value = constructeurLinks.value.map(l => ({ ...l })) toast.showSuccess('Produit mis à jour avec succès') await loadProduct() isEditMode.value = false @@ -600,6 +618,25 @@ const submitEdition = async () => { } } +// Sync constructeurIds → constructeurLinks when IDs are added via ConstructeurSelect +watch( + () => editionForm.constructeurIds, + (ids) => { + const currentIds = new Set(constructeurLinks.value.map(l => l.constructeurId)) + for (const id of ids) { + if (!currentIds.has(id)) { + const resolved = getConstructeurById(id) + constructeurLinks.value.push({ + constructeurId: id, + constructeur: resolved ? { id: resolved.id, name: resolved.name } : null, + supplierReference: null, + }) + } + } + constructeurLinks.value = constructeurLinks.value.filter(l => ids.includes(l.constructeurId)) + }, +) + onMounted(async () => { await loadProduct() if (route.query.edit === 'true' && canEdit.value) { diff --git a/app/pages/product/create.vue b/app/pages/product/create.vue index a0653ef..451240e 100644 --- a/app/pages/product/create.vue +++ b/app/pages/product/create.vue @@ -79,6 +79,11 @@
+ +