From 5e15c1f69f0bb752e914fe0c0dff66d0edce1096 Mon Sep 17 00:00:00 2001 From: tristan Date: Mon, 22 Jun 2026 09:40:40 +0000 Subject: [PATCH] =?UTF-8?q?fix=20:=20retours=20m=C3=A9tier=20ERP-193=20(4?= =?UTF-8?q?=20r=C3=A9pertoires)=20(#139)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lot de retours métier **ERP-193** (« Fix tous les retours starseed »), transverse aux 4 répertoires (clients, fournisseurs, prestataires, transporteurs). ## Contenu - **Pagination** : défaut à 25 items/page sur les 4 répertoires. - **Libellé** : colonne « Dernière activité » → « Dernière modification ». - **Consultation** : masquage des onglets vides (coquilles « à venir » + onglets de données sans donnée). - **Chiffre d'affaires** : plafonné à 999 999 999 999,99 (clamp front + `Assert\LessThanOrEqual` back). - **Date de création** : interdiction des dates futures (`:max` MalioDate + `Assert\LessThanOrEqual('today')` back). - **Caractères spéciaux** : blocage des caractères parasites (`²³§~#|…`) dans les champs texte via une allow-list par profil (nom de personne / texte libre / adresse / code alphanumérique) — filtrage front à la frappe + `Assert\Regex` back autoritaire. Email/IBAN/BIC/TVA conservent leurs validateurs de format. - **UI** : champs en consultation et onglets validés grisés (`readonly` → `disabled`). - **UI** : boutons « Archiver » en rouge (variant `danger`). ## Tests - Back : nouveaux tests RG (plafond CA, dates futures, caractères spéciaux) + garde-fou contraintes — suite complète verte (813 tests). - Front : nouveaux tests unitaires (sanitizers, helpers date/montant) — 615 tests verts, eslint clean. --------- Co-authored-by: THOLOT DECHENE Matthieu Reviewed-on: https://gitea.malio.fr/MALIO-DEV/Starseed/pulls/139 Co-authored-by: tristan Co-committed-by: tristan --- frontend/i18n/locales/fr.json | 22 +- .../components/ClientAddressBlock.vue | 104 ++++++++-- .../components/ClientContactBlock.vue | 29 ++- .../components/SupplierAddressBlock.vue | 110 ++++++++-- .../components/SupplierContactBlock.vue | 29 ++- .../__tests__/ClientAddressBlock.spec.ts | 176 ++++++++++++++++ .../__tests__/useClientsRepository.spec.ts | 10 +- .../__tests__/useSuppliersRepository.spec.ts | 10 +- .../composables/useClientsRepository.ts | 3 +- .../composables/useSuppliersRepository.ts | 3 +- .../commercial/pages/clients/[id]/edit.vue | 94 ++++++--- .../commercial/pages/clients/[id]/index.vue | 124 +++++++---- .../commercial/pages/clients/index.vue | 6 +- .../modules/commercial/pages/clients/new.vue | 98 ++++++--- .../commercial/pages/suppliers/[id]/edit.vue | 88 +++++--- .../commercial/pages/suppliers/[id]/index.vue | 113 +++++++---- .../commercial/pages/suppliers/index.vue | 4 +- .../commercial/pages/suppliers/new.vue | 87 +++++--- .../utils/forms/__tests__/amountInput.spec.ts | 33 +++ .../__tests__/clientConsultation.spec.ts | 73 +++++++ .../__tests__/supplierConsultation.spec.ts | 60 ++++++ .../commercial/utils/forms/amountInput.ts | 29 +++ .../utils/forms/clientConsultation.ts | 71 +++++++ .../utils/forms/supplierConsultation.ts | 72 +++++++ .../components/ProviderAddressBlock.vue | 111 +++++++--- .../components/ProviderContactBlock.vue | 29 ++- .../__tests__/ProviderAddressBlock.spec.ts | 6 +- .../__tests__/useProviderForm.test.ts | 9 +- .../__tests__/useProvidersRepository.test.ts | 2 +- .../technique/composables/useProviderForm.ts | 8 + .../composables/useProvidersRepository.ts | 3 +- .../technique/pages/providers/[id]/edit.vue | 38 ++-- .../technique/pages/providers/[id]/index.vue | 84 +++++--- .../technique/pages/providers/index.vue | 4 +- .../modules/technique/pages/providers/new.vue | 46 +++-- .../modules/technique/types/providerForm.ts | 3 - .../forms/__tests__/providerAddress.spec.ts | 15 +- .../forms/__tests__/providerDetail.spec.ts | 51 ++++- .../technique/utils/forms/providerAddress.ts | 9 +- .../technique/utils/forms/providerDetail.ts | 54 ++++- .../components/CarrierAddressBlock.vue | 92 +++++++-- .../components/CarrierContactBlock.vue | 29 ++- .../components/CarrierPriceBlock.vue | 24 ++- .../__tests__/useCarrierForm.test.ts | 45 ++-- .../__tests__/useCarriersRepository.test.ts | 2 +- .../transport/composables/useCarrierForm.ts | 38 ++-- .../composables/useCarriersRepository.ts | 3 +- .../transport/pages/carriers/[id]/edit.vue | 41 ++-- .../transport/pages/carriers/[id]/index.vue | 192 +++++++++++------- .../modules/transport/pages/carriers/new.vue | 52 +++-- .../forms/__tests__/carrierMappers.test.ts | 50 +++++ .../utils/forms/__tests__/numberInput.test.ts | 13 +- .../transport/utils/forms/carrierContact.ts | 21 +- .../transport/utils/forms/carrierMappers.ts | 65 +++++- .../transport/utils/forms/numberInput.ts | 23 ++- frontend/package-lock.json | 8 +- frontend/package.json | 2 +- .../utils/__tests__/collectionRow.test.ts | 10 +- .../__tests__/consultationDisplay.test.ts | 23 +++ frontend/shared/utils/__tests__/date.test.ts | 19 ++ .../utils/__tests__/textSanitize.test.ts | 65 ++++++ frontend/shared/utils/collectionRow.ts | 14 +- frontend/shared/utils/consultationDisplay.ts | 37 ++++ frontend/shared/utils/date.ts | 17 ++ frontend/shared/utils/textSanitize.ts | 47 +++++ migrations/Version20260619120000.php | 47 +++++ migrations/Version20260622100000.php | 74 +++++++ .../Commercial/Domain/Entity/Client.php | 11 + .../Domain/Entity/ClientAddress.php | 4 + .../Domain/Entity/ClientContact.php | 4 + .../Commercial/Domain/Entity/Supplier.php | 11 + .../Domain/Entity/SupplierAddress.php | 4 + .../Domain/Entity/SupplierContact.php | 4 + .../Technique/Domain/Entity/Provider.php | 7 +- .../Domain/Entity/ProviderAddress.php | 92 ++------- .../Domain/Entity/ProviderContact.php | 4 + .../Processor/ProviderAddressProcessor.php | 3 +- .../DataFixtures/ProviderFixtures.php | 13 +- .../Transport/Domain/Entity/Carrier.php | 2 + .../Domain/Entity/CarrierAddress.php | 4 + .../Domain/Entity/CarrierContact.php | 10 +- .../Processor/CarrierContactProcessor.php | 46 +---- .../DataFixtures/CarrierFixtures.php | 3 +- .../Domain/Validation/TextInputPattern.php | 51 +++++ .../Database/ColumnCommentsCatalog.php | 12 +- ...EntityConstraintsHaveFrenchMessageTest.php | 5 +- .../Commercial/Api/FoundedAtFutureTest.php | 85 ++++++++ .../Commercial/Api/RevenueAmountCapTest.php | 81 ++++++++ .../Api/TextInputSanitizationTest.php | 93 +++++++++ .../Api/AbstractProviderApiTestCase.php | 1 - .../Api/ProviderSerializationContractTest.php | 5 - .../Api/ProviderSubResourceApiTest.php | 42 +--- .../Transport/Api/CarrierContactApiTest.php | 24 +-- 93 files changed, 2791 insertions(+), 803 deletions(-) create mode 100644 frontend/modules/commercial/utils/forms/__tests__/amountInput.spec.ts create mode 100644 frontend/modules/commercial/utils/forms/amountInput.ts create mode 100644 frontend/shared/utils/__tests__/consultationDisplay.test.ts create mode 100644 frontend/shared/utils/__tests__/date.test.ts create mode 100644 frontend/shared/utils/__tests__/textSanitize.test.ts create mode 100644 frontend/shared/utils/consultationDisplay.ts create mode 100644 frontend/shared/utils/date.ts create mode 100644 frontend/shared/utils/textSanitize.ts create mode 100644 migrations/Version20260619120000.php create mode 100644 migrations/Version20260622100000.php create mode 100644 src/Shared/Domain/Validation/TextInputPattern.php create mode 100644 tests/Module/Commercial/Api/FoundedAtFutureTest.php create mode 100644 tests/Module/Commercial/Api/RevenueAmountCapTest.php create mode 100644 tests/Module/Commercial/Api/TextInputSanitizationTest.php diff --git a/frontend/i18n/locales/fr.json b/frontend/i18n/locales/fr.json index 3205c85..cc62b73 100644 --- a/frontend/i18n/locales/fr.json +++ b/frontend/i18n/locales/fr.json @@ -71,7 +71,7 @@ "companyName": "Nom", "categories": "Catégories", "sites": "Site", - "lastActivity": "Dernière activité" + "lastActivity": "Dernière modification" }, "filters": { "title": "Filtres", @@ -125,7 +125,7 @@ }, "edit": { "title": "Modifier le fournisseur", - "back": "Retour au répertoire", + "back": "Retour à la consultation", "loading": "Chargement du fournisseur…", "notFound": "Fournisseur introuvable.", "save": "Enregistrer" @@ -215,7 +215,7 @@ "companyName": "Nom", "categories": "Catégories", "sites": "Site", - "lastActivity": "Dernière activité" + "lastActivity": "Dernière modification" }, "filters": { "title": "Filtres", @@ -268,7 +268,7 @@ }, "edit": { "title": "Modifier le client", - "back": "Retour au répertoire", + "back": "Retour à la consultation", "loading": "Chargement du client…", "notFound": "Client introuvable.", "save": "Enregistrer" @@ -385,7 +385,7 @@ "companyName": "Nom", "categories": "Catégories", "sites": "Site", - "lastActivity": "Dernière activité" + "lastActivity": "Dernière modification" }, "filters": { "title": "Filtres", @@ -420,7 +420,7 @@ }, "edit": { "title": "Modifier le prestataire", - "back": "Retour à la fiche", + "back": "Retour à la consultation", "loading": "Chargement…", "notFound": "Prestataire introuvable.", "save": "Enregistrer" @@ -453,7 +453,6 @@ }, "address": { "sites": "Sites", - "categories": "Catégorie", "contacts": "Contact(s) rattaché(s)", "country": "Pays", "postalCode": "Code postal", @@ -509,7 +508,7 @@ "name": "Nom", "certification": "Certification", "validityDate": "Date de validité", - "lastActivity": "Dernière activité" + "lastActivity": "Dernière modification" }, "certification": { "QUALIMAT": "QUALIMAT", @@ -558,8 +557,8 @@ "message": "Ce transporteur réapparaîtra dans le répertoire actif. Confirmer la restauration ?" }, "price": { - "group": "Type de transport", - "carrier": "Transporteurs", + "group": "Transport", + "carrier": "Fournisseurs / Clients", "aproOrSite": "Adresse sites", "delivery": "Adresse livraisons", "forfait": "Forfait (€)", @@ -790,7 +789,8 @@ "auth": { "logout": "Deconnexion reussie" }, - "title": "Succès" + "title": "Succès", + "deleted": "Suppression effectuée" }, "admin": { "roles": { diff --git a/frontend/modules/commercial/components/ClientAddressBlock.vue b/frontend/modules/commercial/components/ClientAddressBlock.vue index ff2c574..8e5886a 100644 --- a/frontend/modules/commercial/components/ClientAddressBlock.vue +++ b/frontend/modules/commercial/components/ClientAddressBlock.vue @@ -2,7 +2,7 @@
@@ -33,17 +34,21 @@ :label="t('commercial.clients.form.address.sites')" :display-tag="true" :readonly="readonly" - :required="true" + :disabled="disabled" + :required="!readonly && !disabled" :error="errors?.sites" @update:model-value="(v: (string | number)[]) => update('siteIris', v.map(String))" /> + @@ -55,8 +60,9 @@ v-if="isBillingEmailRequired(model)" :model-value="model.billingEmail" :label="t('commercial.clients.form.address.billingEmail')" - :required="true" + :required="!readonly && !disabled" :readonly="readonly" + :disabled="disabled" :lowercase="true" :error="errors?.billingEmail" :addable="!model.hasSecondaryBillingEmail && !readonly" @@ -64,13 +70,17 @@ @update:model-value="(v: string) => update('billingEmail', v)" @add="revealSecondaryBillingEmail" /> -