All checks were successful
Auto Tag Develop / tag (push) Successful in 6s
| Numéro du ticket | Titre du ticket | |------------------|-----------------| | | | ## Description de la PR ## Modification du .env ## Check list - [x] Pas de régression - [x] TU/TI/TF rédigée - [x] TU/TI/TF OK - [x] CHANGELOG modifié Reviewed-on: #42 Co-authored-by: tristan <tristan@yuno.malio.fr> Co-committed-by: tristan <tristan@yuno.malio.fr>
10 KiB
10 KiB
CLAUDE.md
Stack
- Backend: Symfony 8 + API Platform 4 (PHP 8.4)
- Frontend: Nuxt 4 (Vue 3, Pinia, Tailwind, Zod) in
frontend/ - Infra: Docker (PHP-FPM + Nginx), Apache vhost serves API sous
/apiet frontend depuisfrontend/dist
Commands
# Docker
make start # Démarrer les containers
make stop # Arrêter les containers
make restart # Redémarrer les containers
make shell # Shell dans le container PHP
# Install complet
make install # composer install + migrations + build frontend
# Backend
make composer-install # Installer dépendances PHP
make migration-migrate # Lancer les migrations
make fixtures # Charger les fixtures
make cache-clear # Vider le cache Symfony
make test # Lancer les tests PHPUnit
make test FILES=tests/path/to/TestFile.php # Test spécifique
make php-cs-fixer-allow-risky FILES=src/... # Fixer le style
# Frontend
make build-nuxtJS # npm install + build:dist (dans le container)
make dev-nuxt # Serveur dev Nuxt (dans le container)
# Ou directement dans frontend/ :
cd frontend && npm run dev # Dev server (port 3000)
cd frontend && npm run build:dist # Build production
# Base de données
make db-reset # ⚠️ Supprime et recrée la BDD + migrations + fixtures
Architecture backend
src/
├── ApiResource/ # Ressources API Platform custom
├── Command/ # Commandes Symfony (dont app:seed)
├── DataFixtures/ # Fixtures Doctrine
├── Dto/ # DTOs (ex: PontBasculeReading)
├── Entity/ # Entités Doctrine (= ressources API Platform)
├── Exception/ # Exceptions custom (PontBasculeException)
├── Kernel.php
├── Service/ # Services métier (PontBasculePayloadDecoder…)
└── State/ # State providers/processors API Platform
Architecture frontend
frontend/
├── components/
│ ├── ui/ # Composants réutilisables, auto-importés avec préfixe Ui (ex: UiLoadingDots)
│ ├── 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)
├── utils/ # Constants, zod-errors helpers
└── assets/css/ # Tailwind config, main.css (font Helvetica)
Conventions backend
- Code en anglais ; "pont-bascule" est un terme métier conservé tel quel.
- Les opérations API Platform sont définies directement sur les entités Doctrine.
- Pas de classes Repository custom : utiliser
EntityManagerInterfaceavec les repos par défaut. config/reference.phpest 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,CustomeretCarriersont automatiquement mis en majuscule viamb_strtoupperdanssetName().
Conventions frontend
- SSR désactivé. Tailwind avec palette custom
primary(ex:bg-primary-500). useApi(composables/useApi.ts) : méthodesget/post/put/patch/deleteavec content-types par défaut.- Toasts personnalisables via
toastErrorMessage/toastSuccessMessageou clés i18ntoastErrorKey/toastSuccessKey. - Utilise
useNuxtApp().$i18n(pasuseI18n) pour fonctionner hors setup.
- Toasts personnalisables via
- Validation formulaires avec Zod ; helpers dans
utils/zod-errors.ts. - Nav active :
NuxtLinkavec slotcustom. - PDFs :
usePdfPrinter(receipt réception, rapport poids cases).
Validation required & erreurs visuelles
- Les champs
requiredutilisent l'attribut HTML natif forwardé viav-bind="attrs"dans les composants UI. - La bordure rouge n'apparaît qu'après soumission grâce à la classe CSS
submittedajoutée sur le<form>au clic sur le bouton Valider (@click="submitted = true"). - Règles CSS globales dans
main.css:.submitted :invalid(bordure + texte rouge),.submitted :has(:invalid) > labelet.submitted label:has(:invalid)(labels rouges). - Pour les validations manuelles (checkboxes, radio groups), les messages d'erreur utilisent
invisible(pashidden) 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<input type="date">).
Workflow réception/expédition (mutualisé)
- Factory service
createWorkflowServiceet factory storeuseWorkflowStoreLogicpour é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 (remplaceuseWeighing+useWeighingShipment).- Configs workflow dans
config/reception.config.tsetconfig/shipment.config.ts(étapes, labels pesée, filename PDF). WorkflowWeightcomposant partagé pour les étapes de pesée (remplacereception-weight.vueetshipment-weight.vue).WorkflowWaitingListcomposant partagé pour les listes en attente, avec support colonnes dynamiques, slotactions, et propshowActions.
Domaine métier clé
Réception (pesée pont-bascule)
- Entité principale
Reception:date_reception(DateTimeImmutable, format lectureY-m-d H:i, écritureY-m-d),identification_number(autoN-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]].vuebasée surcurrentStep. PrePersist: injecte l'heure courante surreceptionDateà la création ;setReceptionDatepréserve l'heure existante au PATCH.
Expédition
- Entité
Shipment: même pattern que Reception,shipment_date(format lectureY-m-d H:i, écritureY-m-d). - Endpoint suppression :
DELETE /shipments/{id}. PrePersist: injecte l'heure courante surshipmentDate;setShipmentDatepré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).BuildingCaseabovines(OneToMany).- Rapport PDF cases :
GET /building_cases/{id}/weights-report→ template Twig, projection depuisarrivalDate, gain journalier fixe1.3 kg/jour.
Scanner boucles auriculaires
- Page dédiée
/scan: scan de codes-barres Code 39/128 (boucles auriculaires bovines) depuis un téléphone Android via Chrome. - Utilise l'API native
BarcodeDetector(Shape Detection API, Chrome Android 83+) — pas de lib JS, décodage hardware quasi-instantané. - Non supporté sur iOS (tous les navigateurs iOS utilisent WebKit, qui n'implémente pas
BarcodeDetector). - Les 4 premiers caractères du code-barres sont retirés avant enregistrement (
rawValue.slice(4)). - Composable
useBarcodeScanner: caméra arrière, anti-doublon 2s, vibration au scan. - Le bovin est créé via
POST /bovinesavecContent-Type: application/ld+json(nécessaire pour la résolution d'IRI debuildingCase). - Sélection bâtiment → case (filtrées dynamiquement) avant de scanner.
Données de référence
ReceptionType,MerchandiseType,PelletType,Building,Supplier(avecAddressvia join table,createdBy→ User),Customer(avecAddressvia join table,createdBy→ User),Truck,Carrier,Driver,Vehicle.Address: champlabelnullable (déprécié, retiré du front et duaddress:write), exposefullAddressvia getter.countryCodepar défautFRcô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.
upsertAddresscherche parstreet|postalCode(plus parlabel).- Fixtures :
BuildingInfrastructureFixtures+BovineFixtures(via dépendancesAppFixtures).
Environnement
- API base dev :
http://localhost:8080/api(viaNUXT_PUBLIC_API_BASEdansfrontend/.env) - CORS : Nelmio, configurable via
CORS_ALLOW_ORIGINdans.env - Locale par défaut :
fr— traductions dansfrontend/i18n/locales/fr.json - Docker env :
docker/.env.docker(défaut) avec override possible viadocker/.env.docker.local