From 9e2206a7d6d8171e5c017e1937321d2132cc08bc Mon Sep 17 00:00:00 2001 From: tristan Date: Wed, 24 Jun 2026 15:33:12 +0200 Subject: [PATCH] =?UTF-8?q?fix=20:=20DSD=20saisi=20conserv=C3=A9=20en=20pe?= =?UTF-8?q?s=C3=A9e=20manuelle=20(ERP-193)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit En pesée manuelle, le serveur incrémentait automatiquement le DSD et ignorait la saisie de l'opérateur. Désormais l'opérateur saisit le poids ET le DSD (le numéro du pont réellement utilisé), conservés tels quels — plus d'auto-incrément. Le champ « Numéro de pesée » séparé (manualNumber) est supprimé : pour le client c'est la même chose que le DSD. Pas de contrainte d'unicité sur le DSD (doublons autorisés). Colonnes empty_manual_number/full_manual_number droppées. --- frontend/i18n/locales/fr.json | 4 +- .../__tests__/useWeighbridge.spec.ts | 11 +++-- .../__tests__/useWeighingTicketForm.spec.ts | 7 +-- .../logistique/composables/useWeighbridge.ts | 14 +++--- .../composables/useWeighingTicket.ts | 2 - .../composables/useWeighingTicketForm.ts | 13 +---- .../pages/weighing-tickets/[id]/edit.vue | 21 ++++---- .../logistique/pages/weighing-tickets/new.vue | 21 ++++---- migrations/Version20260624110000.php | 41 ++++++++++++++++ .../Domain/Entity/WeighingTicket.php | 36 -------------- .../Resource/WeighbridgeReadingResource.php | 48 +++++++++++-------- .../Processor/WeighbridgeReadingProcessor.php | 18 ++++--- .../Database/ColumnCommentsCatalog.php | 44 ++++++++--------- .../weighing_ticket_print.html.twig | 11 ++--- .../Api/WeighbridgeReadingApiTest.php | 27 +++++++---- .../WeighbridgeReadingProcessorTest.php | 39 +++++---------- 16 files changed, 175 insertions(+), 182 deletions(-) create mode 100644 migrations/Version20260624110000.php diff --git a/frontend/i18n/locales/fr.json b/frontend/i18n/locales/fr.json index 95e6485..56e766d 100644 --- a/frontend/i18n/locales/fr.json +++ b/frontend/i18n/locales/fr.json @@ -741,10 +741,10 @@ "manual": { "title": "Pesée manuelle", "weight": "Poids (Kg)", - "number": "Numéro de pesée", + "dsd": "DSD", "save": "Enregistrer", "weightRequired": "Le poids est obligatoire.", - "numberRequired": "Le numéro de pesée est obligatoire." + "dsdRequired": "Le DSD est obligatoire." } }, "edit": { diff --git a/frontend/modules/logistique/composables/__tests__/useWeighbridge.spec.ts b/frontend/modules/logistique/composables/__tests__/useWeighbridge.spec.ts index 8ff8e72..2004b50 100644 --- a/frontend/modules/logistique/composables/__tests__/useWeighbridge.spec.ts +++ b/frontend/modules/logistique/composables/__tests__/useWeighbridge.spec.ts @@ -26,18 +26,19 @@ describe('useWeighbridge', () => { expect(reading).toEqual({ weight: 23187, dsd: 42, mode: 'AUTO' }) }) - it('MANUAL : POST { mode: MANUAL, weight, manualNumber } et renvoie la lecture', async () => { - mockPost.mockResolvedValue({ weight: 5000, dsd: 43, manualNumber: 'PAP-555', mode: 'MANUAL' }) + it('MANUAL : POST { mode: MANUAL, weight, dsd } et renvoie la lecture', async () => { + // Le DSD est saisi par l'opérateur et conservé tel quel (ERP-193). + mockPost.mockResolvedValue({ weight: 5000, dsd: 16619, mode: 'MANUAL' }) const { triggerManual } = useWeighbridge() - const reading = await triggerManual(5000, 'PAP-555') + const reading = await triggerManual(5000, 16619) expect(mockPost).toHaveBeenCalledWith( '/weighbridge_readings', - { mode: 'MANUAL', weight: 5000, manualNumber: 'PAP-555' }, + { mode: 'MANUAL', weight: 5000, dsd: 16619 }, expect.objectContaining({ toast: false }), ) - expect(reading.dsd).toBe(43) + expect(reading.dsd).toBe(16619) }) it('erreur (RG-5.06) : extractWeighbridgeError privilégie le detail du 503', () => { diff --git a/frontend/modules/logistique/composables/__tests__/useWeighingTicketForm.spec.ts b/frontend/modules/logistique/composables/__tests__/useWeighingTicketForm.spec.ts index de61652..f820710 100644 --- a/frontend/modules/logistique/composables/__tests__/useWeighingTicketForm.spec.ts +++ b/frontend/modules/logistique/composables/__tests__/useWeighingTicketForm.spec.ts @@ -106,11 +106,12 @@ describe('useWeighingTicketForm', () => { expect(form.empty.weight).toBe(7150) expect(form.empty.dsd).toBe(1) expect(form.empty.mode).toBe('AUTO') - expect(form.empty.manualNumber).toBeNull() - form.applyReading(form.full, { weight: 14300, dsd: 2, mode: 'MANUAL', manualNumber: 'PAP-555' }) + // Pesée manuelle : le DSD saisi (16619) est conservé tel quel (ERP-193). + form.applyReading(form.full, { weight: 14300, dsd: 16619, mode: 'MANUAL' }) expect(form.full.weight).toBe(14300) - expect(form.full.manualNumber).toBe('PAP-555') + expect(form.full.dsd).toBe(16619) + expect(form.full.mode).toBe('MANUAL') }) it('buildDraftPayload porte les pesées effectuées ; buildValidatePayload les 4 champs du haut', () => { diff --git a/frontend/modules/logistique/composables/useWeighbridge.ts b/frontend/modules/logistique/composables/useWeighbridge.ts index 2f08b19..a582f76 100644 --- a/frontend/modules/logistique/composables/useWeighbridge.ts +++ b/frontend/modules/logistique/composables/useWeighbridge.ts @@ -7,8 +7,8 @@ * - AUTO (« Pesée bascule ») : le serveur résout le site courant, lit le poids * (stub aléatoire au M5) et alloue le DSD. Peut échouer (RG-5.06 → 503) : le * pont est indisponible, on invite l'utilisateur à passer en pesée manuelle. - * - MANUAL (« Pesée manuelle ») : poids + numéro de pesée saisis ; le serveur - * calcule le DSD = dernier + 1 (RG-5.04). + * - MANUAL (« Pesée manuelle ») : poids + DSD saisis par l'opérateur ; le serveur + * les conserve tels quels — plus d'auto-incrément (ERP-193). * * Composable UI-agnostique : il appelle l'API (`useApi`, jamais `$fetch`) et * renvoie la lecture, ou lève l'erreur — la gestion de la modal/de l'affichage @@ -24,8 +24,6 @@ export interface WeighbridgeReading { weight: number dsd: number mode: WeighbridgeMode - /** Numéro de pesée saisi en mode MANUAL (absent en AUTO). */ - manualNumber?: string } export function useWeighbridge() { @@ -46,13 +44,13 @@ export function useWeighbridge() { } /** - * Pesée manuelle (MANUAL). Le DSD est calculé serveur (dernier + 1, RG-5.04) ; - * le `manualNumber` est la référence du ticket papier / autre bascule. + * Pesée manuelle (MANUAL). Le poids ET le DSD sont saisis par l'opérateur (le + * DSD = numéro du pont réellement utilisé) et conservés tels quels (ERP-193). */ - async function triggerManual(weight: number, manualNumber: string): Promise { + async function triggerManual(weight: number, dsd: number): Promise { return await api.post( '/weighbridge_readings', - { mode: 'MANUAL', weight, manualNumber }, + { mode: 'MANUAL', weight, dsd }, { toast: false }, ) } diff --git a/frontend/modules/logistique/composables/useWeighingTicket.ts b/frontend/modules/logistique/composables/useWeighingTicket.ts index 6865c8e..52cdea9 100644 --- a/frontend/modules/logistique/composables/useWeighingTicket.ts +++ b/frontend/modules/logistique/composables/useWeighingTicket.ts @@ -25,13 +25,11 @@ export interface WeighingTicketDetail { emptyWeight?: number | null emptyDsd?: number | null emptyMode?: WeighbridgeMode | null - emptyManualNumber?: string | null // Pesée à plein fullDate?: string | null fullWeight?: number | null fullDsd?: number | null fullMode?: WeighbridgeMode | null - fullManualNumber?: string | null netWeight?: number | null } diff --git a/frontend/modules/logistique/composables/useWeighingTicketForm.ts b/frontend/modules/logistique/composables/useWeighingTicketForm.ts index 04c490c..7f4c63f 100644 --- a/frontend/modules/logistique/composables/useWeighingTicketForm.ts +++ b/frontend/modules/logistique/composables/useWeighingTicketForm.ts @@ -32,12 +32,10 @@ export interface WeighingBlockState { date: string | null /** Poids en kg — readonly, rempli par la pesée (bascule ou manuelle). */ weight: number | null - /** DSD — readonly, rempli par la pesée (RG-5.04). */ + /** DSD — pesée bascule : fourni par le pont ; pesée manuelle : saisi (RG-5.04, ERP-193). */ dsd: number | null /** Mode de la dernière pesée appliquée au bloc. */ mode: WeighbridgeMode | null - /** Numéro de pesée (rempli uniquement en pesée manuelle). */ - manualNumber: string | null } /** Cycle de vie du ticket (miroir back, ERP-193). */ @@ -57,12 +55,10 @@ export interface WeighingTicketHydration { emptyWeight?: number | null emptyDsd?: number | null emptyMode?: WeighbridgeMode | null - emptyManualNumber?: string | null fullDate?: string | null fullWeight?: number | null fullDsd?: number | null fullMode?: WeighbridgeMode | null - fullManualNumber?: string | null } /** @@ -95,7 +91,6 @@ function emptyBlock(now: string): WeighingBlockState { weight: null, dsd: null, mode: null, - manualNumber: null, } } @@ -172,13 +167,12 @@ export function useWeighingTicketForm() { */ function applyReading( block: WeighingBlockState, - reading: { weight: number, dsd: number, mode: WeighbridgeMode, manualNumber?: string }, + reading: { weight: number, dsd: number, mode: WeighbridgeMode }, ): void { block.date = nowIsoDateTime() block.weight = reading.weight block.dsd = reading.dsd block.mode = reading.mode - block.manualNumber = reading.manualNumber ?? null } /** Partie « contrepartie » du payload (FK en IRI ou libellé libre). */ @@ -203,7 +197,6 @@ export function useWeighingTicketForm() { [`${prefix}Weight`]: block.weight, [`${prefix}Dsd`]: block.dsd, [`${prefix}Mode`]: block.mode, - [`${prefix}ManualNumber`]: block.manualNumber || null, } } @@ -245,13 +238,11 @@ export function useWeighingTicketForm() { empty.weight = detail.emptyWeight ?? null empty.dsd = detail.emptyDsd ?? null empty.mode = detail.emptyMode ?? null - empty.manualNumber = detail.emptyManualNumber ?? null full.date = toLocalIsoDateTime(detail.fullDate) ?? now full.weight = detail.fullWeight ?? null full.dsd = detail.fullDsd ?? null full.mode = detail.fullMode ?? null - full.manualNumber = detail.fullManualNumber ?? null } /** diff --git a/frontend/modules/logistique/pages/weighing-tickets/[id]/edit.vue b/frontend/modules/logistique/pages/weighing-tickets/[id]/edit.vue index 140ef64..1b7085b 100644 --- a/frontend/modules/logistique/pages/weighing-tickets/[id]/edit.vue +++ b/frontend/modules/logistique/pages/weighing-tickets/[id]/edit.vue @@ -166,10 +166,11 @@ :error="manualModal.errors.weight" />