161 lines
9.5 KiB
Markdown
161 lines
9.5 KiB
Markdown
# 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 `/api` et frontend depuis `frontend/dist`
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
# 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 `EntityManagerInterface` avec les repos par défaut.
|
|
- `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
|
|
|
|
- SSR désactivé. Tailwind avec palette custom `primary` (ex: `bg-primary-500`).
|
|
- `useApi` (`composables/useApi.ts`) : méthodes `get/post/put/patch/delete` avec content-types par défaut.
|
|
- Toasts personnalisables via `toastErrorMessage`/`toastSuccessMessage` ou clés i18n `toastErrorKey`/`toastSuccessKey`.
|
|
- Utilise `useNuxtApp().$i18n` (pas `useI18n`) pour fonctionner hors setup.
|
|
- Validation formulaires avec Zod ; helpers dans `utils/zod-errors.ts`.
|
|
- 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 `<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) > 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 `<input type="date">`).
|
|
|
|
### 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 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).
|
|
- `BuildingCase` a `bovines` (OneToMany).
|
|
- 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, `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
|
|
|
|
- API base dev : `http://localhost:8080/api` (via `NUXT_PUBLIC_API_BASE` dans `frontend/.env`)
|
|
- CORS : Nelmio, configurable via `CORS_ALLOW_ORIGIN` dans `.env`
|
|
- Locale par défaut : `fr` — traductions dans `frontend/i18n/locales/fr.json`
|
|
- Docker env : `docker/.env.docker` (défaut) avec override possible via `docker/.env.docker.local`
|