From 07f5a95a6b8edc81cc58a371741706e220f31632 Mon Sep 17 00:00:00 2001 From: tristan Date: Fri, 19 Jun 2026 09:46:23 +0200 Subject: [PATCH] =?UTF-8?q?feat=20:=20bloque=20les=20caract=C3=A8res=20sp?= =?UTF-8?q?=C3=A9ciaux=20dans=20les=20champs=20texte=20des=204=20r=C3=A9pe?= =?UTF-8?q?rtoires=20(ERP-193)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/ClientAddressBlock.vue | 19 +++- .../components/ClientContactBlock.vue | 18 +++- .../components/SupplierAddressBlock.vue | 17 +++- .../components/SupplierContactBlock.vue | 18 +++- .../commercial/pages/clients/[id]/edit.vue | 22 +++-- .../modules/commercial/pages/clients/new.vue | 22 +++-- .../commercial/pages/suppliers/[id]/edit.vue | 22 +++-- .../commercial/pages/suppliers/new.vue | 22 +++-- .../components/ProviderAddressBlock.vue | 16 +++- .../components/ProviderContactBlock.vue | 18 +++- .../technique/pages/providers/[id]/edit.vue | 16 +++- .../modules/technique/pages/providers/new.vue | 16 +++- .../components/CarrierAddressBlock.vue | 17 +++- .../components/CarrierContactBlock.vue | 18 +++- .../transport/pages/carriers/[id]/edit.vue | 4 +- .../modules/transport/pages/carriers/new.vue | 8 +- .../utils/__tests__/textSanitize.test.ts | 70 ++++++++++++++ frontend/shared/utils/textSanitize.ts | 58 ++++++++++++ .../Commercial/Domain/Entity/Client.php | 6 ++ .../Domain/Entity/ClientAddress.php | 4 + .../Domain/Entity/ClientContact.php | 4 + .../Commercial/Domain/Entity/Supplier.php | 6 ++ .../Domain/Entity/SupplierAddress.php | 4 + .../Domain/Entity/SupplierContact.php | 4 + .../Technique/Domain/Entity/Provider.php | 4 + .../Domain/Entity/ProviderAddress.php | 4 + .../Domain/Entity/ProviderContact.php | 4 + .../Transport/Domain/Entity/Carrier.php | 2 + .../Domain/Entity/CarrierAddress.php | 4 + .../Domain/Entity/CarrierContact.php | 4 + .../Domain/Validation/TextInputPattern.php | 51 ++++++++++ .../Api/TextInputSanitizationTest.php | 93 +++++++++++++++++++ 32 files changed, 537 insertions(+), 58 deletions(-) create mode 100644 frontend/shared/utils/__tests__/textSanitize.test.ts create mode 100644 frontend/shared/utils/textSanitize.ts create mode 100644 src/Shared/Domain/Validation/TextInputPattern.php create mode 100644 tests/Module/Commercial/Api/TextInputSanitizationTest.php diff --git a/frontend/modules/commercial/components/ClientAddressBlock.vue b/frontend/modules/commercial/components/ClientAddressBlock.vue index ff2c574..db956fe 100644 --- a/frontend/modules/commercial/components/ClientAddressBlock.vue +++ b/frontend/modules/commercial/components/ClientAddressBlock.vue @@ -191,6 +191,7 @@ import { import { useAddressAutocomplete, type AddressSuggestion } from '~/shared/composables/useAddressAutocomplete' import type { CategoryOption, RefOption } from '~/modules/commercial/composables/useClientReferentials' import type { AddressFormDraft } from '~/modules/commercial/types/clientForm' +import { sanitizeAddress, sanitizeEmail } from '~/shared/utils/textSanitize' // Masque code postal FR : 5 chiffres. const POSTAL_CODE_MASK = '#####' @@ -284,9 +285,23 @@ const addressLoading = ref(false) // Conserve les suggestions d'adresse pour retrouver ville/CP au moment du select. let lastAddressSuggestions: AddressSuggestion[] = [] -/** Emet un nouveau brouillon avec le champ modifie (immutabilite). */ +// Filtres de saisie par champ (ERP-193) : voie / complement / ville = profil +// adresse, emails de facturation = profil email. +const FIELD_SANITIZERS: Partial string>> = { + street: sanitizeAddress, + streetComplement: sanitizeAddress, + city: sanitizeAddress, + billingEmail: sanitizeEmail, + billingEmailSecondary: sanitizeEmail, +} + +/** Emet un nouveau brouillon avec le champ modifie (immutabilite), sanitise si besoin. */ function update(field: K, value: AddressFormDraft[K]): void { - emit('update:modelValue', { ...props.modelValue, [field]: value }) + const sanitizer = FIELD_SANITIZERS[field] + const next = (sanitizer && typeof value === 'string') + ? (sanitizer(value) as AddressFormDraft[K]) + : value + emit('update:modelValue', { ...props.modelValue, [field]: next }) } /** Revele le 2e champ email de facturation (clic sur le « + »). */ diff --git a/frontend/modules/commercial/components/ClientContactBlock.vue b/frontend/modules/commercial/components/ClientContactBlock.vue index e4284c7..0ecfd86 100644 --- a/frontend/modules/commercial/components/ClientContactBlock.vue +++ b/frontend/modules/commercial/components/ClientContactBlock.vue @@ -71,6 +71,7 @@