fix(piece) : persist slot quantity on blur and send prix as string
- Save composant piece slot quantity via PATCH on blur - Pass slotId through hierarchy and selection entries - Send prix as string (not number) to match backend expectation - Show quantity in view mode when > 1 - Allow quantity edit for all pieces (not just root-level) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -69,7 +69,7 @@
|
||||
<div v-show="!isCollapsed" class="space-y-4">
|
||||
<div class="p-4 bg-base-100 border border-base-200 rounded-lg">
|
||||
<div class="space-y-2 text-sm">
|
||||
<div v-if="!piece.parentComponentLinkId && isEditMode" class="form-control">
|
||||
<div v-if="isEditMode" class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text text-sm">Quantité</span>
|
||||
</label>
|
||||
@@ -82,6 +82,10 @@
|
||||
@blur="updatePiece"
|
||||
/>
|
||||
</div>
|
||||
<div v-else-if="displayQuantity > 1">
|
||||
<span class="font-medium">Quantité:</span>
|
||||
<span class="ml-2">{{ displayQuantity }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="font-medium">Référence:</span>
|
||||
<input
|
||||
@@ -456,7 +460,7 @@ const updatePiece = () => {
|
||||
let parsedPrice = null
|
||||
if (prixValue !== null && prixValue !== undefined && String(prixValue).trim().length > 0) {
|
||||
const numeric = Number(prixValue)
|
||||
if (!Number.isNaN(numeric)) parsedPrice = numeric
|
||||
if (!Number.isNaN(numeric)) parsedPrice = String(numeric)
|
||||
}
|
||||
const product = selectedProduct.value ? { ...selectedProduct.value } : null
|
||||
emit('update', {
|
||||
|
||||
@@ -7,6 +7,7 @@ import { useProductTypes } from '~/composables/useProductTypes'
|
||||
import { usePieces } from '~/composables/usePieces'
|
||||
import { useProducts } from '~/composables/useProducts'
|
||||
import { useCustomFields } from '~/composables/useCustomFields'
|
||||
import type { SelectionEntry } from '~/shared/utils/structureSelectionUtils'
|
||||
import { useApi } from '~/composables/useApi'
|
||||
import { useToast } from '~/composables/useToast'
|
||||
import { extractRelationId } from '~/shared/apiRelations'
|
||||
@@ -53,7 +54,7 @@ const historyFieldLabels: Record<string, string> = {
|
||||
export function useComponentEdit(componentId: string) {
|
||||
const { canEdit } = usePermissions()
|
||||
const router = useRouter()
|
||||
const { get } = useApi()
|
||||
const { get, patch } = useApi()
|
||||
const { componentTypes, loadComponentTypes } = useComponentTypes()
|
||||
const { pieceTypes, loadPieceTypes } = usePieceTypes()
|
||||
const { productTypes, loadProductTypes } = useProductTypes()
|
||||
@@ -269,6 +270,21 @@ export function useComponentEdit(componentId: string) {
|
||||
}
|
||||
})
|
||||
|
||||
const saveSlotQuantity = async (entry: SelectionEntry) => {
|
||||
const slotId = entry.slotId
|
||||
const quantity = typeof entry._definition?.quantity === 'number'
|
||||
? Math.max(1, entry._definition.quantity)
|
||||
: null
|
||||
if (!slotId || quantity === null) return
|
||||
try {
|
||||
await patch(`/composant-piece-slots/${slotId}`, { quantity })
|
||||
toast.showSuccess('Quantité mise à jour')
|
||||
}
|
||||
catch (error: any) {
|
||||
toast.showError(error?.message || 'Erreur lors de la mise à jour de la quantité')
|
||||
}
|
||||
}
|
||||
|
||||
const submitEdition = async () => {
|
||||
if (!component.value) {
|
||||
return
|
||||
@@ -299,10 +315,6 @@ export function useComponentEdit(componentId: string) {
|
||||
payload.prix = null
|
||||
}
|
||||
|
||||
if (component.value.structure) {
|
||||
payload.structure = component.value.structure
|
||||
}
|
||||
|
||||
saving.value = true
|
||||
try {
|
||||
const result = await updateComposant(component.value.id, payload)
|
||||
@@ -457,6 +469,7 @@ export function useComponentEdit(componentId: string) {
|
||||
handleFilesAdded,
|
||||
refreshDocuments,
|
||||
submitEdition,
|
||||
saveSlotQuantity,
|
||||
resolvePieceLabel,
|
||||
resolveProductLabel,
|
||||
resolveSubcomponentLabel,
|
||||
|
||||
@@ -110,18 +110,18 @@ export function useMachineDetailUpdates(deps: UseMachineDetailUpdatesDeps) {
|
||||
const productId = updatedComponent.productId
|
||||
? String(updatedComponent.productId)
|
||||
: null
|
||||
const prix =
|
||||
const prixStr =
|
||||
updatedComponent.prix !== null &&
|
||||
updatedComponent.prix !== undefined &&
|
||||
String(updatedComponent.prix).trim() !== ''
|
||||
? Number(updatedComponent.prix)
|
||||
? String(updatedComponent.prix)
|
||||
: null
|
||||
|
||||
const result: any = await updateComposantApi(updatedComponent.id as string, {
|
||||
name: updatedComponent.name,
|
||||
reference: updatedComponent.reference,
|
||||
constructeurIds: cIds,
|
||||
prix: Number.isNaN(prix) ? null : prix,
|
||||
prix: prixStr,
|
||||
productId,
|
||||
} as any)
|
||||
if (result.success) {
|
||||
@@ -140,18 +140,18 @@ export function useMachineDetailUpdates(deps: UseMachineDetailUpdatesDeps) {
|
||||
updatedPiece.constructeur,
|
||||
)
|
||||
const productId = updatedPiece.productId ? String(updatedPiece.productId) : null
|
||||
const prix =
|
||||
const prixStr =
|
||||
updatedPiece.prix !== null &&
|
||||
updatedPiece.prix !== undefined &&
|
||||
String(updatedPiece.prix).trim() !== ''
|
||||
? Number(updatedPiece.prix)
|
||||
? String(updatedPiece.prix)
|
||||
: null
|
||||
|
||||
const result: any = await updatePieceApi(updatedPiece.id as string, {
|
||||
name: updatedPiece.name,
|
||||
reference: updatedPiece.reference || null,
|
||||
constructeurIds: cIds,
|
||||
prix: Number.isNaN(prix) ? null : prix,
|
||||
prix: prixStr,
|
||||
productId,
|
||||
} as any)
|
||||
if (result.success) {
|
||||
@@ -181,6 +181,13 @@ export function useMachineDetailUpdates(deps: UseMachineDetailUpdatesDeps) {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Update slot quantity if this is a composant structure piece
|
||||
const slotId = updatedPiece.slotId as string | null
|
||||
const quantity = typeof updatedPiece.quantity === 'number' ? Math.max(1, updatedPiece.quantity) : null
|
||||
if (slotId && quantity !== null) {
|
||||
await apiPatch(`/composant-piece-slots/${slotId}`, { quantity })
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la mise à jour de la pièce:', error)
|
||||
}
|
||||
|
||||
@@ -237,6 +237,7 @@ export const buildMachineHierarchyFromLinks = (
|
||||
constructeurs: resolved?.constructeurs || [],
|
||||
documents: [],
|
||||
quantity,
|
||||
slotId: def.slotId || definition.slotId || null,
|
||||
typePieceId: resolved?.typePieceId || definition.typePieceId || def.typePieceId || null,
|
||||
typePiece: resolved?.typePiece || null,
|
||||
parentComponentLinkId: machineComponentLinkId,
|
||||
|
||||
@@ -179,6 +179,7 @@
|
||||
placeholder="Qté"
|
||||
class="input input-bordered input-xs w-16 ml-auto"
|
||||
@input="entry._definition.quantity = Math.max(1, entry._definition.quantity || 1)"
|
||||
@blur="saveSlotQuantity(entry)"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -319,6 +320,7 @@ const {
|
||||
removeDocument,
|
||||
handleFilesAdded,
|
||||
submitEdition,
|
||||
saveSlotQuantity,
|
||||
resolvePieceLabel,
|
||||
resolveProductLabel,
|
||||
resolveSubcomponentLabel,
|
||||
|
||||
@@ -4,7 +4,7 @@ export interface DefinitionOverridePayload {
|
||||
name?: string
|
||||
reference?: string
|
||||
constructeurIds?: string[]
|
||||
prix?: number
|
||||
prix?: string
|
||||
}
|
||||
|
||||
export const sanitizeDefinitionOverrides = (definition: any): DefinitionOverridePayload | null => {
|
||||
@@ -41,7 +41,7 @@ export const sanitizeDefinitionOverrides = (definition: any): DefinitionOverride
|
||||
if (definition.prix !== undefined && definition.prix !== null && definition.prix !== '') {
|
||||
const parsed = Number(definition.prix)
|
||||
if (!Number.isNaN(parsed)) {
|
||||
payload.prix = parsed
|
||||
payload.prix = String(parsed)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ export type SelectionEntry = {
|
||||
requirementLabel: string
|
||||
resolvedName: string
|
||||
quantity?: number
|
||||
slotId?: string
|
||||
_definition?: Record<string, any>
|
||||
}
|
||||
|
||||
@@ -62,6 +63,7 @@ export function collectStructureSelections(
|
||||
requirementLabel: resolvers.resolvePieceLabel(definition),
|
||||
resolvedName: catalogPiece?.name || selectedId,
|
||||
quantity: typeof definition?.quantity === 'number' ? definition.quantity : undefined,
|
||||
slotId: isNonEmptyString(entry?.slotId) ? entry.slotId : undefined,
|
||||
_definition: definition,
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user