From 149bced1c5f6cdb3b647e20766fc350fa945d119 Mon Sep 17 00:00:00 2001 From: tristan Date: Mon, 2 Feb 2026 17:12:23 +0100 Subject: [PATCH 01/43] =?UTF-8?q?fix=20:=20ne=20fait=20plus=20de=20pes?= =?UTF-8?q?=C3=A9e=20si=20une=20pes=C3=A9e=20existe=20+=20fix=20save=20des?= =?UTF-8?q?=20granul=C3=A9=20+=20fix=20de=20la=20g=C3=A9n=C3=A9ration=20du?= =?UTF-8?q?=20pdf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reception/reception-product-received.vue | 40 +++++++++++++++++-- .../components/reception/reception-weight.vue | 12 ++---- frontend/composables/usePdfPrinter.ts | 21 +++++----- 3 files changed, 50 insertions(+), 23 deletions(-) diff --git a/frontend/components/reception/reception-product-received.vue b/frontend/components/reception/reception-product-received.vue index de451d4..aed56c6 100644 --- a/frontend/components/reception/reception-product-received.vue +++ b/frontend/components/reception/reception-product-received.vue @@ -98,6 +98,30 @@ const selectedBuildingIds = ref([]) const selectedPelletBuildingIds = ref>({}) const merchandiseDetail = ref('') +// Extrait l'ID d'une relation depuis un IRI ou un objet complet. +const getRelationId = (value: unknown): string | null => { + if (!value) { + return null + } + + if (typeof value === 'string') { + const match = value.match(/\/(\d+)$/) + return match ? match[1] : null + } + + if (typeof value === 'object' && 'id' in value) { + const record = value as { id?: number | string } + if (typeof record.id === 'number') { + return String(record.id) + } + if (typeof record.id === 'string') { + return record.id + } + } + + return null +} + // Type de marchandise sélectionné dans le select const selectedMerchandiseType = computed(() => merchandiseTypes.value.find((type) => String(type.id) === selectedMerchandiseTypeId.value) @@ -130,8 +154,12 @@ onMounted(async () => { const existingPelletSelections = receptionStore.current?.pelletBuildings ?? [] const selectionMap: Record = {} for (const selection of existingPelletSelections) { - const pelletTypeId = String(selection.pelletType.id) - const buildingId = String(selection.building.id) + // L'API peut renvoyer les relations comme IRI ou comme objets selon le contexte. + const pelletTypeId = getRelationId(selection.pelletType) + const buildingId = getRelationId(selection.building) + if (!pelletTypeId || !buildingId) { + continue + } if (!selectionMap[pelletTypeId]) { selectionMap[pelletTypeId] = [] } @@ -186,7 +214,13 @@ async function syncPelletSelections(receptionIri: string) { const existing = await getReceptionPelletBuildingList(receptionIri) const existingMap = new Map() for (const selection of existing) { - const key = `${selection.pelletType.id}:${selection.building.id}` + // Construit la table de correspondance avec des IDs normalisés pour éviter les doublons. + const pelletTypeId = getRelationId(selection.pelletType) + const buildingId = getRelationId(selection.building) + if (!pelletTypeId || !buildingId) { + continue + } + const key = `${pelletTypeId}:${buildingId}` existingMap.set(key, selection.id) } diff --git a/frontend/components/reception/reception-weight.vue b/frontend/components/reception/reception-weight.vue index 758b832..7e624d7 100644 --- a/frontend/components/reception/reception-weight.vue +++ b/frontend/components/reception/reception-weight.vue @@ -73,14 +73,8 @@ const printReceipt = async () => { return } - // Ouvre l'onglet tout de suite pour éviter le blocage popup de Chrome - const previewWindow = window.open('', '_blank') - if (previewWindow) { - previewWindow.opener = null - } - await saveWeight() - await printPdf(`/receptions/${receptionStore.current.id}/receipt`, previewWindow) + await printPdf(`/receptions/${receptionStore.current.id}/receipt`) // Laisse le temps a la boite de dialogue d'impression de s'ouvrir. await new Promise((resolve) => setTimeout(resolve, 600)) @@ -98,6 +92,8 @@ const printReceipt = async () => { // Récupère le poids dès l'arrivée sur l'écran onMounted(() => { - fetchWeight() + if (false === displayWeight.value) { + fetchWeight() + } }) diff --git a/frontend/composables/usePdfPrinter.ts b/frontend/composables/usePdfPrinter.ts index e6440f5..ff6a057 100644 --- a/frontend/composables/usePdfPrinter.ts +++ b/frontend/composables/usePdfPrinter.ts @@ -5,7 +5,7 @@ export const usePdfPrinter = () => { const receptionStore = useReceptionStore() const currentReception = receptionStore.current - const printPdf = async (url: string, previewWindow?: Window | null): Promise => { + const printPdf = async (url: string): Promise => { const blob = await api.getBlob(url); const pdfBlob = blob.type === 'application/pdf' @@ -16,17 +16,14 @@ export const usePdfPrinter = () => { const filename = `${currentReception.identificationNumber}_${currentReception.supplier.name}_${currentReception.licensePlate}.pdf`; - if (previewWindow) { - previewWindow.location.replace(blobUrl) - } - - const a = document.createElement('a') - a.href = blobUrl - a.download = filename - a.style.display = 'none' - document.body.appendChild(a) - a.click() - a.remove() + const a = document.createElement('a'); + a.href = blobUrl; + a.download = filename; + a.style.display = 'none'; + document.body.appendChild(a); + a.click(); + a.remove(); + // L'ouverture dans un nouvel onglet déclenche un 2e PDF sans le nom personnalisé. setTimeout(() => URL.revokeObjectURL(blobUrl), 60_000); } From 7c85d91c78a0b8d0050aee3edd55024b708caba7 Mon Sep 17 00:00:00 2001 From: tristan Date: Mon, 2 Feb 2026 17:13:53 +0100 Subject: [PATCH 02/43] feat : ajout de fixtures --- .idea/workspace.xml | 53 +-- src/Command/SeedCommand.php | 496 +++++++++++++++++++------ src/DataFixtures/ReferenceFixtures.php | 238 ++++++++++++ 3 files changed, 645 insertions(+), 142 deletions(-) diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 4fa4df0..0c0069b 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -7,9 +7,11 @@ + - + +