diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml
deleted file mode 100644
index 4fee92a..0000000
--- a/.idea/dataSources.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
- postgresql
- true
- org.postgresql.Driver
- jdbc:postgresql://localhost:5432/ferme
- $ProjectFileDir$
-
-
- postgresql
- true
- org.postgresql.Driver
- jdbc:postgresql://localhost:5432/postgres
- $ProjectFileDir$
-
-
-
diff --git a/.idea/db-forest-config.xml b/.idea/db-forest-config.xml
index 0620fdb..235c8ff 100644
--- a/.idea/db-forest-config.xml
+++ b/.idea/db-forest-config.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 88f52e0..8974e33 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -4,10 +4,13 @@
-
+
+
+
+
-
+
@@ -223,36 +226,36 @@
- {
+ "keyToString": {
+ "RunOnceActivity.MCP Project settings loaded": "true",
+ "RunOnceActivity.ShowReadmeOnStart": "true",
+ "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true",
+ "RunOnceActivity.git.unshallow": "true",
+ "RunOnceActivity.typescript.service.memoryLimit.init": "true",
+ "git-widget-placeholder": "develop",
+ "last_opened_file_path": "/home/sroy/Documents/test/Ferme/frontend/components/commun",
+ "node.js.detected.package.eslint": "true",
+ "node.js.detected.package.tslint": "true",
+ "node.js.selected.package.eslint": "(autodetect)",
+ "node.js.selected.package.tslint": "(autodetect)",
+ "nodejs_package_manager_path": "npm",
+ "settings.editor.selected.configurable": "advanced.settings",
+ "ts.external.directory.path": "/opt/phpstorm/plugins/javascript-plugin/jsLanguageServicesImpl/external",
+ "vue.rearranger.settings.migration": "true"
},
- "keyToStringList": {
- "DatabaseDriversLRU": [
- "postgresql"
+ "keyToStringList": {
+ "DatabaseDriversLRU": [
+ "postgresql"
],
- "com.intellij.ide.scratch.ScratchImplUtil$2/New Scratch File": [
- "TEXT"
+ "com.intellij.ide.scratch.ScratchImplUtil$2/New Scratch File": [
+ "TEXT"
],
- "vue.recent.templates": [
- "Vue Composition API Component"
+ "vue.recent.templates": [
+ "Vue Composition API Component"
]
}
-}]]>
+}
@@ -272,10 +275,11 @@
-
+
+
@@ -310,14 +314,16 @@
-
-
-
- 1769024603812
-
-
-
- 1769024603812
+
+
+
+
+
+
+
+
+
+
@@ -703,7 +709,15 @@
1772182707441
-
+
+
+ 1772447581744
+
+
+
+ 1772447581744
+
+
@@ -753,7 +767,6 @@
-
@@ -778,7 +791,8 @@
-
+
+
diff --git a/AGENTS.md b/AGENTS.md
deleted file mode 100644
index b1aac43..0000000
--- a/AGENTS.md
+++ /dev/null
@@ -1,73 +0,0 @@
-# AGENTS.md
-
-Project overview
-- Symfony 8 + API Platform 4 backend, Nuxt 3 frontend in `frontend/`.
-- Apache vhost serves API under `/api` and frontend from `frontend/dist`.
-- API base URL on frontend uses `NUXT_PUBLIC_API_BASE` (see `frontend/.env`).
-
-Backend conventions
-- Use English for code identifiers/messages; keep “pont-bascule” as domain term.
-- API Platform operations are defined on Doctrine entities.
-- No custom repository classes are used (`src/Repository` removed); use default Doctrine repositories via `EntityManagerInterface`.
-- Reception entity is in `src/Entity/Reception.php`, with custom weigh endpoint `/receptions/weigh`.
-- Reception fields: `date_reception`, `license_plate`, `current_step` (default 0), `is_valid` (default false).
-- Reception also has `identification_number` (auto `N-BR-####`), `merchandise_type`, `merchandise_detail`, `buildings` (M2M), and `pellet_buildings` (via `reception_pellet_building`).
-- `date_reception` is set by the UI, stored as `DateTimeImmutable`, serialized as `Y-m-d`.
-- Weight entity (`src/Entity/Weight.php`) is 1–N with Reception, each row stores `type` (`gross` or `tare`), `dsd`, `weight`, `weighed_at` (all nullable except `type`).
-- Weigh endpoint `/receptions/weigh` returns `PontBasculeReading` with `dsd`, `weight`, `weighedAt` (formatted `Y-m-d`).
-- Custom exception: `App\Exception\PontBasculeException` with French messages, mapped to 500 in provider.
-- Parsing of pont-bascule payload is in `src/Service/PontBasculePayloadDecoder.php`.
-- `config/reference.php` is auto-generated; keep it.
-- Bovine storage:
- - `src/Entity/Bovine.php` with fields `nationalNumber` (unique), `receivedWeight`, `arrivalDate`, and `buildingCase` (ManyToOne).
- - `src/Entity/BuildingCase.php` has `bovines` (OneToMany).
-- Case PDF report:
- - Endpoint: `GET /building_cases/{id}/weights-report` (provider: `App\State\BuildingCaseWeightsReportProvider`).
- - Template: `templates/case_weights_report.html.twig`.
- - Projection logic is done in backend from `arrivalDate`; daily gain is currently fixed at `1.3 kg/day` for all races.
-
-Frontend conventions
-- Nuxt SSR disabled; Tailwind used.
-- Layout in `frontend/layouts/default.vue`: max width `1050px`, header full width.
-- Tailwind custom color palette is `primary` (e.g. `bg-primary-500`).
-- Global font stack uses Helvetica via Tailwind (`font-sans`) and `frontend/assets/css/main.css`.
-- API composable in `frontend/composables/useApi.ts` with `get/post/put/patch/delete` and default JSON/PATCH content types.
-- API errors/success toasts can be customized via `toastErrorMessage`/`toastSuccessMessage` or i18n keys `toastErrorKey`/`toastSuccessKey`. Global method fallbacks use `errors.http.*` keys.
-- `useApi` uses `useNuxtApp().$i18n` (not `useI18n`) to avoid setup-only constraint in service calls.
-- Pinia store: `frontend/stores/reception.ts` is the source of truth for the current reception.
-- Zod is used for form validation (e.g. `frontend/components/reception/reception-form.vue`); shared helpers live in `frontend/utils/zod-errors.ts`.
-- Weighing logic is shared via `frontend/composables/useWeighing.ts`.
-- Reception step UI uses store state (`currentStep`) in `frontend/pages/reception/[[id]].vue`.
-- Step 2 uses `frontend/components/reception/reception-product-received.vue` for merchandise selection; type codes in `frontend/utils/constants.ts`.
-- Active nav styles in header use `NuxtLink` with `custom` slot.
-- Reusable UI components live under `frontend/components/ui/` and are auto-imported with `Ui` prefix (e.g. `UiLoadingDots`).
-- Service layer lives in `frontend/services/` with typed DTOs in `frontend/services/dto/`.
-- Reception service uses `receptions`, `receptions/{id}`, `receptions/weigh` and supports success/error toast keys.
-- Reception receipt endpoint is `receptions/{id}/receipt` (PDF) via `frontend/composables/usePdfPrinter.ts`.
-- Infrastructure case page prints the case weight report PDF from `frontend/pages/infrastructure/case.vue` using `usePdfPrinter('/building_cases/{id}/weights-report')`.
-
-Environment & routing
-- Frontend dev server: `npm run dev` in `frontend/`.
-- API base for local dev: `http://localhost:8080/api` (set in `frontend/.env` via `NUXT_PUBLIC_API_BASE`).
-- CORS handled by Nelmio; `.env` includes `CORS_ALLOW_ORIGIN` regex for localhost.
-- Nuxt i18n locales live in `frontend/i18n/locales` (configured via `langDir: 'locales'`).
-- Default locale is `fr`; translations in `frontend/i18n/locales/fr.json`.
-
-Notes
-- Do not add a GET that creates resources; use POST + PATCH.
-- Keep endpoints in plural (API Platform convention).
-- Seed and fixtures conventions:
- - `app:seed` now seeds infrastructure (`statut`, `building_layout`, `building_case`, `building_case_position`) and bovines.
- - `app:seed` uses intermediate flushes (after buildings and after infrastructure) so find queries can resolve just-created records.
- - Bovine seed rows use a legacy case token mapping to building-case code (`B{building}-C{case}`) before fallback to direct id lookup.
- - Fixtures include `BuildingInfrastructureFixtures` + `BovineFixtures` (via `AppFixtures` dependencies).
-- New reference data added:
- - Reception types (`reception_type`, fields: `label`, `code`), selectable on reception form.
- - Merchandise types (`merchandise_type`, fields: `label`, `code`) and pellet types (`pellet_type`, fields: `label`, `code`).
- - Buildings (`building`, fields: `label`, `code`) and reception allocations (`reception_building` M2M, `reception_pellet_building` unique on reception/pellet/building).
- - Suppliers (`supplier`) with addresses (`address`, fields: `label`, `street`, `postal_code`, `city`, `country_code` ISO2), via `supplier_address` join table.
- - Trucks (`truck`, field: `name`), linked to receptions.
- - Carriers (`carrier`, fields: `name`, nullable `code`), Drivers (`driver`, fields: `name`, `carrier_id`), Vehicles (`vehicle`, fields: `plate`, `carrier_id`, `truck_id`) used for LIOT logic.
- - Reception links: `reception_type_id`, `supplier_id`, `address_id`, `truck_id`, `carrier_id`, `driver_id`, `user_id`.
- - Address exposes `fullAddress` via getter for display.
- - LIOT behavior in reception form: if carrier code = `LIOT`, show driver + vehicle selects and hide manual license plate input; vehicle list filters by truck type and carrier; selected vehicle sets `license_plate`.
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..fbb6785
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,127 @@
+# 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
+├── composables/ # useApi, useWeighing, usePdfPrinter, useAppVersion
+├── services/ # Couche service avec DTOs typés dans services/dto/
+├── stores/ # Pinia stores (reception, shipment, auth)
+├── 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.
+
+## 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).
+
+## 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`.
+- Endpoint pesée : `/receptions/weigh` → `PontBasculeReading` (dsd, weight, weighedAt).
+- 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`.
+
+### 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`.
+
+### 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), `Truck`, `Carrier`, `Driver`, `Vehicle`.
+- `Address` expose `fullAddress` via getter.
+
+### 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.
+- 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`
diff --git a/src/Command/SeedCommand.php b/src/Command/SeedCommand.php
index bd69db1..c83c6eb 100644
--- a/src/Command/SeedCommand.php
+++ b/src/Command/SeedCommand.php
@@ -748,6 +748,36 @@ class SeedCommand extends Command
],
],
],
+ [
+ 'name' => 'EARL DE LA MENAUDIERE',
+ 'email' => 'frederic.doussineau@orange.fr',
+ 'phone' => '0675446004',
+ 'addresses' => [
+ [
+ 'label' => 'EARL DE LA MENAUDIERE',
+ 'street' => '1 la menaudière',
+ 'street2' => null,
+ 'postalCode' => '86450',
+ 'city' => 'LEIGNE LES BOIS ',
+ 'countryCode' => 'FR',
+ ],
+ ],
+ ],
+ [
+ 'name' => 'SARL ERBS',
+ 'email' => 'touillet.jacques@yahoo.fr',
+ 'phone' => '0675030304',
+ 'addresses' => [
+ [
+ 'label' => 'SARL ERBS',
+ 'street' => 'les rodières ',
+ 'street2' => null,
+ 'postalCode' => '86230',
+ 'city' => 'Sérigny',
+ 'countryCode' => 'FR',
+ ],
+ ],
+ ],
];
foreach ($suppliers as $supplierData) {
diff --git a/src/DataFixtures/ReferenceFixtures.php b/src/DataFixtures/ReferenceFixtures.php
index b8751e1..556cacb 100644
--- a/src/DataFixtures/ReferenceFixtures.php
+++ b/src/DataFixtures/ReferenceFixtures.php
@@ -311,6 +311,36 @@ class ReferenceFixtures extends Fixture
],
],
],
+ [
+ 'name' => 'EARL DE LA MENAUDIERE',
+ 'email' => 'frederic.doussineau@orange.fr',
+ 'phone' => '0675446004',
+ 'addresses' => [
+ [
+ 'label' => 'EARL DE LA MENAUDIERE',
+ 'street' => '1 la menaudière',
+ 'street2' => null,
+ 'postalCode' => '86450',
+ 'city' => 'LEIGNE LES BOIS ',
+ 'countryCode' => 'FR',
+ ],
+ ],
+ ],
+ [
+ 'name' => 'SARL ERBS',
+ 'email' => 'touillet.jacques@yahoo.fr',
+ 'phone' => '0675030304',
+ 'addresses' => [
+ [
+ 'label' => 'SARL ERBS',
+ 'street' => 'les rodières ',
+ 'street2' => null,
+ 'postalCode' => '86230',
+ 'city' => 'Sérigny',
+ 'countryCode' => 'FR',
+ ],
+ ],
+ ],
];
foreach ($suppliers as $supplierData) {