From a905c6a1dede586cc7897e2746d2bba08c3ebc86 Mon Sep 17 00:00:00 2001 From: tristan Date: Wed, 18 Mar 2026 14:47:03 +0100 Subject: [PATCH] fix : correction des retours de la V0 --- .claude/settings.local.json | 7 + .idea/workspace.xml | 92 +++- CLAUDE.md | 45 +- frontend/assets/css/main.css | 14 + frontend/components/address.vue | 17 +- frontend/components/commun/update-weight.vue | 3 + .../reception/reception-bovine-received.vue | 21 +- .../components/reception/reception-form.vue | 388 +++-------------- .../reception/reception-product-received.vue | 58 ++- .../components/reception/reception-weight.vue | 95 ----- .../reception/update-merchandise.vue | 42 +- .../components/shipment/shipment-form.vue | 399 ++++-------------- .../components/shipment/shipment-weight.vue | 95 ----- .../components/ui/license-plate-input.vue | 5 +- .../workflow/workflow-liot-fields.vue | 57 +++ .../workflow/workflow-waiting-list.vue | 72 ++++ .../components/workflow/workflow-weight.vue | 78 ++++ frontend/composables/steps/useWeighingStep.ts | 77 ++++ frontend/composables/useAddressSync.ts | 54 +++ frontend/composables/useFormDataLoading.ts | 73 ++++ frontend/composables/useLiotHandling.ts | 153 +++++++ frontend/composables/useWeighing.ts | 169 +++----- frontend/composables/useWorkflowSteps.ts | 83 ++++ frontend/config/reception.config.ts | 25 ++ frontend/config/shipment.config.ts | 25 ++ frontend/constants/steps.ts | 22 - frontend/i18n/locales/fr.json | 8 +- frontend/pages/admin/bovin/[[id]].vue | 8 +- frontend/pages/admin/carrier/[[id]].vue | 6 +- frontend/pages/admin/customer/[[id]].vue | 19 +- .../pages/admin/customer/customer-list.vue | 70 +-- frontend/pages/admin/supplier/[[id]].vue | 19 +- .../pages/admin/supplier/supplier-list.vue | 66 +-- frontend/pages/admin/user/[[id]].vue | 7 +- frontend/pages/reception/[[id]].vue | 98 ++--- frontend/pages/reception/finish-reception.vue | 17 +- frontend/pages/reception/update/[[id]].vue | 110 ++++- .../pages/reception/waiting-reception.vue | 89 ++-- frontend/pages/shipment/[[id]].vue | 87 ++-- frontend/pages/shipment/update/[[id]].vue | 46 +- frontend/pages/shipment/waiting-shipment.vue | 110 ++--- frontend/services/address.ts | 3 +- frontend/services/dto/address-data.ts | 4 +- frontend/services/dto/customer-data.ts | 2 + frontend/services/dto/supplier-data.ts | 2 + frontend/services/reception.ts | 54 +-- frontend/services/shipment.ts | 54 +-- frontend/services/weight.ts | 27 +- frontend/services/workflow-service.ts | 55 +++ frontend/stores/reception.ts | 66 +-- frontend/stores/shipment.ts | 67 +-- frontend/stores/workflow-store.ts | 59 +++ frontend/types/workflow.ts | 48 +++ migrations/Version20260318103644.php | 33 ++ migrations/Version20260318104205.php | 41 ++ src/Command/SeedCommand.php | 30 +- src/DataFixtures/ReferenceFixtures.php | 33 +- src/Entity/Address.php | 10 +- src/Entity/Carrier.php | 2 +- src/Entity/Customer.php | 19 +- src/Entity/Reception.php | 27 +- src/Entity/Shipment.php | 31 +- src/Entity/Supplier.php | 19 +- src/Entity/User.php | 4 +- 64 files changed, 1979 insertions(+), 1640 deletions(-) create mode 100644 .claude/settings.local.json delete mode 100644 frontend/components/reception/reception-weight.vue delete mode 100644 frontend/components/shipment/shipment-weight.vue create mode 100644 frontend/components/workflow/workflow-liot-fields.vue create mode 100644 frontend/components/workflow/workflow-waiting-list.vue create mode 100644 frontend/components/workflow/workflow-weight.vue create mode 100644 frontend/composables/steps/useWeighingStep.ts create mode 100644 frontend/composables/useAddressSync.ts create mode 100644 frontend/composables/useFormDataLoading.ts create mode 100644 frontend/composables/useLiotHandling.ts create mode 100644 frontend/composables/useWorkflowSteps.ts create mode 100644 frontend/config/reception.config.ts create mode 100644 frontend/config/shipment.config.ts delete mode 100644 frontend/constants/steps.ts create mode 100644 frontend/services/workflow-service.ts create mode 100644 frontend/stores/workflow-store.ts create mode 100644 frontend/types/workflow.ts create mode 100644 migrations/Version20260318103644.php create mode 100644 migrations/Version20260318104205.php diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..47b3190 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,7 @@ +{ + "permissions": { + "allow": [ + "Bash(npm run:*)" + ] + } +} diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 75b83ee..084e866 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -4,17 +4,71 @@ - - @@ -798,7 +850,9 @@ - diff --git a/CLAUDE.md b/CLAUDE.md index fbb6785..f1b2667 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -59,10 +59,18 @@ src/ frontend/ ├── components/ │ ├── ui/ # Composants réutilisables, auto-importés avec préfixe Ui (ex: UiLoadingDots) -│ └── reception/ # Composants métier réception -├── composables/ # useApi, useWeighing, usePdfPrinter, useAppVersion +│ ├── reception/ # Composants métier réception +│ ├── shipment/ # Composants métier expédition +│ ├── workflow/ # Composants partagés réception/expédition (workflow-weight, workflow-waiting-list, workflow-liot-fields) +│ └── commun/ # Composants communs (update-weight) +├── composables/ # useApi, useWeighing, usePdfPrinter, useAppVersion, useLiotHandling, useFormDataLoading, useAddressSync, useWorkflowSteps +│ └── steps/ # useWeighingStep (logique étape pesée) +├── config/ # reception.config.ts, shipment.config.ts (WorkflowConfig) +├── types/ # workflow.ts (interfaces partagées WorkflowEntity, WorkflowConfig, StepDefinition) ├── services/ # Couche service avec DTOs typés dans services/dto/ +│ └── workflow-service.ts # Factory service API (createWorkflowService) ├── stores/ # Pinia stores (reception, shipment, auth) +│ └── workflow-store.ts # Factory store (useWorkflowStoreLogic) ├── pages/ # Pages Nuxt (file-based routing) ├── layouts/ # Layout default : max-width 1050px ├── i18n/locales/ # Traductions (défaut: fr) @@ -78,6 +86,7 @@ frontend/ - `config/reference.php` est auto-généré — ne pas modifier à la main. - Endpoints toujours au pluriel (convention API Platform). - Ne jamais créer de GET qui crée des ressources : utiliser POST + PATCH. +- Les noms de `Supplier`, `Customer` et `Carrier` sont automatiquement mis en majuscule via `mb_strtoupper` dans `setName()`. ## Conventions frontend @@ -89,21 +98,44 @@ frontend/ - Nav active : `NuxtLink` avec slot `custom`. - PDFs : `usePdfPrinter` (receipt réception, rapport poids cases). +### Validation required & erreurs visuelles +- Les champs `required` utilisent l'attribut HTML natif forwardé via `v-bind="attrs"` dans les composants UI. +- La bordure rouge n'apparaît qu'après soumission grâce à la classe CSS `submitted` ajoutée sur le `
` au clic sur le bouton Valider (`@click="submitted = true"`). +- Règles CSS globales dans `main.css` : `.submitted :invalid` (bordure + texte rouge), `.submitted :has(:invalid) > label` et `.submitted label:has(:invalid)` (labels rouges). +- Pour les validations manuelles (checkboxes, radio groups), les messages d'erreur utilisent `invisible` (pas `hidden`) pour garder l'espace réservé et éviter les décalages de layout. +- Les dates de l'API sont renvoyées au format `Y-m-d H:i` ; les formulaires utilisent `.slice(0, 10)` pour extraire la date seule (compatible ``). + +### Workflow réception/expédition (mutualisé) +- Factory service `createWorkflowService` et factory store `useWorkflowStoreLogic` pour éviter la duplication. +- Composables partagés : `useLiotHandling` (logique LIOT), `useFormDataLoading` (users, trucks, carriers), `useAddressSync` (sync adresse fournisseur/client). +- `useWeighing` : une seule fonction paramétrée pour réception et expédition (remplace `useWeighing` + `useWeighingShipment`). +- Configs workflow dans `config/reception.config.ts` et `config/shipment.config.ts` (étapes, labels pesée, filename PDF). +- `WorkflowWeight` composant partagé pour les étapes de pesée (remplace `reception-weight.vue` et `shipment-weight.vue`). +- `WorkflowWaitingList` composant partagé pour les listes en attente, avec support colonnes dynamiques, slot `actions`, et prop `showActions`. + ## Domaine métier clé ### Réception (pesée pont-bascule) -- Entité principale `Reception` : `date_reception` (DateTimeImmutable, format `Y-m-d`), `identification_number` (auto `N-BR-####`), `current_step` (défaut 0), `is_valid` (défaut false). -- `Weight` (1-N avec Reception) : `type` (`gross`/`tare`), `dsd`, `weight`, `weighed_at`. +- Entité principale `Reception` : `date_reception` (DateTimeImmutable, format lecture `Y-m-d H:i`, écriture `Y-m-d`), `identification_number` (auto `N-BR-####`), `current_step` (défaut 0), `is_valid` (défaut false). +- `Weight` (1-N avec Reception, cascade remove + orphanRemoval) : `type` (`gross`/`tare`), `dsd`, `weight`, `weighed_at`. - Endpoint pesée : `/receptions/weigh` → `PontBasculeReading` (dsd, weight, weighedAt). +- Endpoint suppression : `DELETE /receptions/{id}` — supprime en cascade weights, pelletBuildings, bovines. - Parsing payload pont-bascule : `Service/PontBasculePayloadDecoder.php`. - Exception : `PontBasculeException` (messages en français, mappée 500). - Store Pinia `reception.ts` = source de vérité pour la réception en cours. - UI multi-étapes dans `pages/reception/[[id]].vue` basée sur `currentStep`. +- `PrePersist` : injecte l'heure courante sur `receptionDate` à la création ; `setReceptionDate` préserve l'heure existante au PATCH. + +### Expédition +- Entité `Shipment` : même pattern que Reception, `shipment_date` (format lecture `Y-m-d H:i`, écriture `Y-m-d`). +- Endpoint suppression : `DELETE /shipments/{id}`. +- `PrePersist` : injecte l'heure courante sur `shipmentDate` ; `setShipmentDate` préserve l'heure au PATCH. ### LIOT (transport) - Si carrier code = `LIOT` : afficher sélecteurs driver + vehicle, masquer saisie plaque manuelle. - Liste véhicules filtrée par type de camion et transporteur. - Le véhicule sélectionné alimente `license_plate`. +- Logique mutualisée dans `composables/useLiotHandling.ts`. ### Bovins & infrastructure - `Bovine` : `nationalNumber` (unique), `receivedWeight`, `arrivalDate`, `buildingCase` (ManyToOne). @@ -111,12 +143,13 @@ frontend/ - Rapport PDF cases : `GET /building_cases/{id}/weights-report` → template Twig, projection depuis `arrivalDate`, gain journalier fixe `1.3 kg/jour`. ### Données de référence -- `ReceptionType`, `MerchandiseType`, `PelletType`, `Building`, `Supplier` (avec `Address` via join table), `Truck`, `Carrier`, `Driver`, `Vehicle`. -- `Address` expose `fullAddress` via getter. +- `ReceptionType`, `MerchandiseType`, `PelletType`, `Building`, `Supplier` (avec `Address` via join table, `createdBy` → User), `Customer` (avec `Address` via join table, `createdBy` → User), `Truck`, `Carrier`, `Driver`, `Vehicle`. +- `Address` : champ `label` nullable (déprécié, retiré du front et du `address:write`), expose `fullAddress` via getter. `countryCode` par défaut `FR` côté front. ### Seed & fixtures - Commande `app:seed` : seed infrastructure (statut, building_layout, building_case, building_case_position) puis bovins. - Utilise des flush intermédiaires pour que les queries find fonctionnent sur les records fraîchement créés. +- `upsertAddress` cherche par `street|postalCode` (plus par `label`). - Fixtures : `BuildingInfrastructureFixtures` + `BovineFixtures` (via dépendances `AppFixtures`). ## Environnement diff --git a/frontend/assets/css/main.css b/frontend/assets/css/main.css index 1119c1b..8b1addf 100644 --- a/frontend/assets/css/main.css +++ b/frontend/assets/css/main.css @@ -7,3 +7,17 @@ @apply font-sans; } } + +@layer utilities { + .submitted :invalid { + @apply border-red-500 text-red-500; + } + + .submitted :has(:invalid) > label { + @apply text-red-500; + } + + .submitted label:has(:invalid) { + @apply text-red-500; + } +} diff --git a/frontend/components/address.vue b/frontend/components/address.vue index bce2fe9..a6ab4c8 100644 --- a/frontend/components/address.vue +++ b/frontend/components/address.vue @@ -1,5 +1,5 @@