diff --git a/.idea/ferme.iml b/.idea/ferme.iml index 6a0c96f..5065845 100644 --- a/.idea/ferme.iml +++ b/.idea/ferme.iml @@ -152,6 +152,8 @@ + + diff --git a/.idea/php.xml b/.idea/php.xml index d4b4d6a..fbd036e 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -158,6 +158,8 @@ + + diff --git a/.idea/workspace.xml b/.idea/workspace.xml index b16884b..0bea72f 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -4,8 +4,10 @@ - - + + + + { @@ -216,7 +220,7 @@ "RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager.252": "true", "RunOnceActivity.git.unshallow": "true", "RunOnceActivity.typescript.service.memoryLimit.init": "true", - "git-widget-placeholder": "feat/installation-soap-bundle", + "git-widget-placeholder": "feat/finalisation-reception-marchandise", "node.js.detected.package.eslint": "true", "node.js.detected.package.tslint": "true", "node.js.selected.package.eslint": "(autodetect)", @@ -239,11 +243,11 @@ } + - @@ -268,7 +272,10 @@ - + + + + - @@ -600,16 +687,6 @@ - - - - - - - - - - @@ -625,7 +702,17 @@ - diff --git a/AGENTS.md b/AGENTS.md index 58d6072..3aa6687 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,6 +10,7 @@ Backend conventions - API Platform operations are defined on Doctrine entities. - 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`). @@ -21,6 +22,7 @@ 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. @@ -28,6 +30,7 @@ Frontend conventions - 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/`. @@ -44,3 +47,13 @@ Environment & routing Notes - Do not add a GET that creates resources; use POST + PATCH. - Keep endpoints in plural (API Platform convention). +- 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/CHANGELOG.md b/CHANGELOG.md index bdef038..05c904f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ Ajouter dans le fichier .env du frontend * [#203] Réceptions — Parcours de pesée multi-étapes (début) * [#202] Authentification — Connexion utilisateur (JWT) * Ajout du bundle malio/ednotif-bundle +* Ajout de composant UI +* Finalisation de la partie réception de marchandise ### Changed diff --git a/README.md b/README.md index 9835150..d4b0c61 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,18 @@ Le frontend ne lit jamais directement le token, le navigateur envoie automatique - Le cookie est automatiquement envoyé pour les futures requêtes. - La déconnexion utilise `POST /api/logout` et redirige vers `/login`. +### Fixtures +Pour lancer les fixtures (Attention sa purge la bdd complètement) +```bash +php bin/console doctrine:fixtures:load +``` + +Attention cette commande est dangereuse, à utiliser que pour les débuts de la prod ou en recette. +Dans un premier temps pour remplir les listes, vous pouvez lancer la commande symfony +```bash +php bin/console app:seed +``` +La commande va faire une update ou une création en fonction des data existante. ## Livraison en recette ### Préparatifs diff --git a/composer.json b/composer.json index b09f4a0..74cc8b9 100644 --- a/composer.json +++ b/composer.json @@ -88,6 +88,7 @@ } }, "require-dev": { + "doctrine/doctrine-fixtures-bundle": "^4.3", "friendsofphp/php-cs-fixer": "^3.92", "phpunit/phpunit": "^12.5", "symfony/browser-kit": "8.0.*", diff --git a/composer.lock b/composer.lock index d308752..4bcf255 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d66ef6b521a08a262b1c043bb32cafe5", + "content-hash": "9c4e168c0540baf5d7d5d54040834d79", "packages": [ { "name": "api-platform/doctrine-common", @@ -8615,6 +8615,175 @@ ], "time": "2024-05-06T16:37:16+00:00" }, + { + "name": "doctrine/data-fixtures", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/data-fixtures.git", + "reference": "7a615ba135e45d67674bb623d90f34f6c7b6bd97" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/data-fixtures/zipball/7a615ba135e45d67674bb623d90f34f6c7b6bd97", + "reference": "7a615ba135e45d67674bb623d90f34f6c7b6bd97", + "shasum": "" + }, + "require": { + "doctrine/persistence": "^3.1 || ^4.0", + "php": "^8.1", + "psr/log": "^1.1 || ^2 || ^3" + }, + "conflict": { + "doctrine/dbal": "<3.5 || >=5", + "doctrine/orm": "<2.14 || >=4", + "doctrine/phpcr-odm": "<1.3.0" + }, + "require-dev": { + "doctrine/coding-standard": "^14", + "doctrine/dbal": "^3.5 || ^4", + "doctrine/mongodb-odm": "^1.3.0 || ^2.0.0", + "doctrine/orm": "^2.14 || ^3", + "ext-sqlite3": "*", + "fig/log-test": "^1", + "phpstan/phpstan": "2.1.31", + "phpunit/phpunit": "10.5.45 || 12.4.0", + "symfony/cache": "^6.4 || ^7", + "symfony/var-exporter": "^6.4 || ^7" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "For using MongoDB ODM 1.3 with PHP 7 (deprecated)", + "doctrine/mongodb-odm": "For loading MongoDB ODM fixtures", + "doctrine/orm": "For loading ORM fixtures", + "doctrine/phpcr-odm": "For loading PHPCR ODM fixtures" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\DataFixtures\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + } + ], + "description": "Data Fixtures for all Doctrine Object Managers", + "homepage": "https://www.doctrine-project.org", + "keywords": [ + "database" + ], + "support": { + "issues": "https://github.com/doctrine/data-fixtures/issues", + "source": "https://github.com/doctrine/data-fixtures/tree/2.2.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdata-fixtures", + "type": "tidelift" + } + ], + "time": "2025-10-17T20:06:20+00:00" + }, + { + "name": "doctrine/doctrine-fixtures-bundle", + "version": "4.3.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/DoctrineFixturesBundle.git", + "reference": "9e013ed10d49bf7746b07204d336384a7d9b5a4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/DoctrineFixturesBundle/zipball/9e013ed10d49bf7746b07204d336384a7d9b5a4d", + "reference": "9e013ed10d49bf7746b07204d336384a7d9b5a4d", + "shasum": "" + }, + "require": { + "doctrine/data-fixtures": "^2.2", + "doctrine/doctrine-bundle": "^2.2 || ^3.0", + "doctrine/orm": "^2.14.0 || ^3.0", + "doctrine/persistence": "^2.4 || ^3.0 || ^4.0", + "php": "^8.1", + "psr/log": "^2 || ^3", + "symfony/config": "^6.4 || ^7.0 || ^8.0", + "symfony/console": "^6.4 || ^7.0 || ^8.0", + "symfony/dependency-injection": "^6.4 || ^7.0 || ^8.0", + "symfony/deprecation-contracts": "^2.1 || ^3", + "symfony/doctrine-bridge": "^6.4.16 || ^7.1.9 || ^8.0", + "symfony/http-kernel": "^6.4 || ^7.0 || ^8.0" + }, + "conflict": { + "doctrine/dbal": "< 3" + }, + "require-dev": { + "doctrine/coding-standard": "14.0.0", + "phpstan/phpstan": "2.1.11", + "phpunit/phpunit": "^10.5.38 || 11.4.14" + }, + "type": "symfony-bundle", + "autoload": { + "psr-4": { + "Doctrine\\Bundle\\FixturesBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Doctrine Project", + "homepage": "https://www.doctrine-project.org" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DoctrineFixturesBundle", + "homepage": "https://www.doctrine-project.org", + "keywords": [ + "Fixture", + "persistence" + ], + "support": { + "issues": "https://github.com/doctrine/DoctrineFixturesBundle/issues", + "source": "https://github.com/doctrine/DoctrineFixturesBundle/tree/4.3.1" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Fdoctrine-fixtures-bundle", + "type": "tidelift" + } + ], + "time": "2025-12-03T16:05:42+00:00" + }, { "name": "evenement/evenement", "version": "v3.0.2", diff --git a/config/bundles.php b/config/bundles.php index 5531a12..b2da949 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -4,6 +4,7 @@ declare(strict_types=1); use ApiPlatform\Symfony\Bundle\ApiPlatformBundle; use Doctrine\Bundle\DoctrineBundle\DoctrineBundle; +use Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle; use Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle; use Lexik\Bundle\JWTAuthenticationBundle\LexikJWTAuthenticationBundle; use Malio\EdnotifBundle\EdnotifBundle; @@ -26,4 +27,5 @@ return [ MonologBundle::class => ['all' => true], EdnotifBundle::class => ['all' => true], WebProfilerBundle::class => ['dev' => true], + DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], ]; diff --git a/frontend/assets/css/main.css b/frontend/assets/css/main.css new file mode 100644 index 0000000..1119c1b --- /dev/null +++ b/frontend/assets/css/main.css @@ -0,0 +1,9 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + body { + @apply font-sans; + } +} diff --git a/frontend/components/reception/reception-form.vue b/frontend/components/reception/reception-form.vue index f4f1f24..14e684e 100644 --- a/frontend/components/reception/reception-form.vue +++ b/frontend/components/reception/reception-form.vue @@ -1,22 +1,119 @@ diff --git a/frontend/components/ui/UiDateInput.vue b/frontend/components/ui/UiDateInput.vue new file mode 100644 index 0000000..9bc95c6 --- /dev/null +++ b/frontend/components/ui/UiDateInput.vue @@ -0,0 +1,62 @@ + + + diff --git a/frontend/components/ui/UiSelect.vue b/frontend/components/ui/UiSelect.vue new file mode 100644 index 0000000..ca57336 --- /dev/null +++ b/frontend/components/ui/UiSelect.vue @@ -0,0 +1,85 @@ + + + diff --git a/frontend/components/ui/UiTextInput.vue b/frontend/components/ui/UiTextInput.vue new file mode 100644 index 0000000..faa1514 --- /dev/null +++ b/frontend/components/ui/UiTextInput.vue @@ -0,0 +1,68 @@ + + + diff --git a/frontend/components/ui/license-plate-input.vue b/frontend/components/ui/license-plate-input.vue index 37dc521..479212a 100644 --- a/frontend/components/ui/license-plate-input.vue +++ b/frontend/components/ui/license-plate-input.vue @@ -1,26 +1,27 @@ @@ -78,13 +79,7 @@ const handleInput = (event: Event) => { emit('update:modelValue', target.value) } -const toggleAllowAny = (event: Event) => { - const target = event.target as HTMLInputElement | null - if (!target) { - return - } - - const nextValue = target.checked +const handleAllowAnyChange = (nextValue: boolean) => { emit('update:allowAny', nextValue) if (!nextValue) { emit('update:modelValue', props.modelValue) diff --git a/frontend/components/ui/pdf-printer.vue b/frontend/components/ui/pdf-printer.vue deleted file mode 100644 index a78f78c..0000000 --- a/frontend/components/ui/pdf-printer.vue +++ /dev/null @@ -1,20 +0,0 @@ -