From 71db3418e373a9b2ddf9a4904f7d872301ac35cb Mon Sep 17 00:00:00 2001 From: tristan Date: Thu, 11 Jun 2026 08:53:06 +0200 Subject: [PATCH] fix(front) : RIB neuf vide soumis (422 inline) quand c'est le seul RIB restant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Onglet Comptabilite : on ne saute une amorce RIB neuve vide QUE s'il reste un autre RIB soumettable (garde hasSubmittableRib, miroir de l'onglet Contacts). Sinon — ex. unique RIB existant supprime puis remplace par un bloc vide en LCR — le bloc vide est soumis et le back renvoie une 422 NotBlank mappee en rouge sous label/bic/iban, au lieu de laisser le DELETE echouer en « dernier RIB d'une LCR » (message plat sans propertyPath). L'ancien RIB est preserve (arret avant le DELETE). Applique creation + edition, fournisseur + client. --- .../commercial/pages/clients/[id]/edit.vue | 15 +++++++++------ frontend/modules/commercial/pages/clients/new.vue | 13 +++++++------ .../commercial/pages/suppliers/[id]/edit.vue | 8 ++++++-- .../modules/commercial/pages/suppliers/new.vue | 8 +++++--- 4 files changed, 27 insertions(+), 17 deletions(-) diff --git a/frontend/modules/commercial/pages/clients/[id]/edit.vue b/frontend/modules/commercial/pages/clients/[id]/edit.vue index af955cc..74f22d7 100644 --- a/frontend/modules/commercial/pages/clients/[id]/edit.vue +++ b/frontend/modules/commercial/pages/clients/[id]/edit.vue @@ -953,8 +953,11 @@ async function submitAccounting(): Promise { try { // 1) POST/PATCH des RIB d'abord (erreurs inline par ligne, tous les blocs // tentes). Le back exige >=1 RIB persiste pour valider une LCR a l'etape 2. - // Seuls les blocs RIB TOTALEMENT vides sont ignores : un RIB partiel (ex. - // IBAN seul) est soumis -> 422 NotBlank (label / bic / iban) inline. + // On ne saute une amorce neuve vide QUE s'il reste un autre RIB soumettable : + // sinon (ex. l'unique RIB existant supprime, remplace par un bloc vide), on la + // soumet pour declencher la 422 NotBlank inline plutot que de laisser le DELETE + // echouer en « dernier RIB d'une LCR » (message plat sans propertyPath). + const hasSubmittableRib = ribs.value.some(r => r.id !== null || !isRibBlank(r)) const ribHasError = await submitRows( ribs.value, ribErrors, @@ -975,10 +978,10 @@ async function submitAccounting(): Promise { } }, error => showError(error), - // On ne saute QUE les amorces neuves (id null) totalement vides. Un - // RIB existant vide est soumis -> 422 NotBlank inline (sinon la modif - // serait perdue en silence avec un faux toast de succes). - rib => rib.id === null && isRibBlank(rib), + // On ne saute une amorce neuve (id null) totalement vide que si un autre RIB + // est soumettable. Un RIB existant vide est toujours soumis -> 422 NotBlank + // inline (sinon la modif serait perdue en silence avec un faux toast succes). + rib => hasSubmittableRib && rib.id === null && isRibBlank(rib), ) if (ribHasError) return diff --git a/frontend/modules/commercial/pages/clients/new.vue b/frontend/modules/commercial/pages/clients/new.vue index 1fa03d1..67be80f 100644 --- a/frontend/modules/commercial/pages/clients/new.vue +++ b/frontend/modules/commercial/pages/clients/new.vue @@ -920,8 +920,9 @@ async function submitAccounting(): Promise { try { // 1) POST/PATCH des RIB d'abord (erreurs inline par ligne, tous les blocs // tentes). Le back exige >=1 RIB persiste pour valider une LCR a l'etape 2. - // Seuls les blocs RIB TOTALEMENT vides sont ignores : un RIB partiel (ex. - // IBAN seul) est soumis -> 422 NotBlank (label / bic / iban) inline. + // On ne saute une amorce neuve vide QUE s'il reste un autre RIB soumettable : + // sinon (LCR sans aucun RIB rempli) on la soumet -> 422 NotBlank inline. + const hasSubmittableRib = ribs.value.some(r => r.id !== null || !isRibBlank(r)) const ribHasError = await submitRows( ribs.value, ribErrors, @@ -941,10 +942,10 @@ async function submitAccounting(): Promise { } }, error => toast.error({ title: t('commercial.clients.toast.error'), message: apiErrorMessage(error) }), - // On ne saute QUE les amorces neuves (id null) totalement vides. Un - // RIB existant vide est soumis -> 422 NotBlank inline (sinon la modif - // serait perdue en silence avec un faux toast de succes). - rib => rib.id === null && isRibBlank(rib), + // On ne saute une amorce neuve (id null) totalement vide que si un autre RIB + // est soumettable. Un RIB existant vide est toujours soumis -> 422 NotBlank + // inline (sinon la modif serait perdue en silence avec un faux toast succes). + rib => hasSubmittableRib && rib.id === null && isRibBlank(rib), ) if (ribHasError) return diff --git a/frontend/modules/commercial/pages/suppliers/[id]/edit.vue b/frontend/modules/commercial/pages/suppliers/[id]/edit.vue index 3bb78b5..8936e8c 100644 --- a/frontend/modules/commercial/pages/suppliers/[id]/edit.vue +++ b/frontend/modules/commercial/pages/suppliers/[id]/edit.vue @@ -841,7 +841,11 @@ async function submitAccounting(): Promise { accountingErrors.clearErrors() try { // 1) POST/PATCH des RIB d'abord (erreurs inline par ligne, tous les blocs - // tentes). Seuls les blocs RIB TOTALEMENT vides (amorce neuve) sont ignores. + // tentes). On ne saute une amorce neuve vide QUE s'il reste un autre RIB + // soumettable : sinon (ex. l'unique RIB existant supprime, remplace par un + // bloc vide), on la soumet pour declencher la 422 NotBlank inline plutot que + // de laisser le DELETE echouer en « dernier RIB d'une LCR » (message plat). + const hasSubmittableRib = ribs.value.some(r => r.id !== null || !isRibBlank(r)) const ribHasError = await submitRows( ribs.value, ribErrors, @@ -862,7 +866,7 @@ async function submitAccounting(): Promise { } }, error => showError(error), - rib => rib.id === null && isRibBlank(rib), + rib => hasSubmittableRib && rib.id === null && isRibBlank(rib), ) if (ribHasError) return diff --git a/frontend/modules/commercial/pages/suppliers/new.vue b/frontend/modules/commercial/pages/suppliers/new.vue index 1419c44..3101184 100644 --- a/frontend/modules/commercial/pages/suppliers/new.vue +++ b/frontend/modules/commercial/pages/suppliers/new.vue @@ -782,8 +782,10 @@ async function submitAccounting(): Promise { tabSubmitting.value = true accountingErrors.clearErrors() try { - // 1) POST/PATCH des RIB d'abord (erreurs inline par ligne). Seuls les blocs - // RIB TOTALEMENT vides (amorce neuve) sont ignores. + // 1) POST/PATCH des RIB d'abord (erreurs inline par ligne). On ne saute une + // amorce neuve vide QUE s'il reste un autre RIB soumettable : sinon (LCR sans + // aucun RIB rempli) on la soumet pour declencher la 422 NotBlank inline. + const hasSubmittableRib = ribs.value.some(r => r.id !== null || !isRibBlank(r)) const ribHasError = await submitRows( ribs.value, ribErrors, @@ -802,7 +804,7 @@ async function submitAccounting(): Promise { } }, error => toast.error({ title: t('commercial.suppliers.toast.error'), message: apiErrorMessage(error) }), - rib => rib.id === null && isRibBlank(rib), + rib => hasSubmittableRib && rib.id === null && isRibBlank(rib), ) if (ribHasError) return