From 0cc2b2730a3ffbe9cc282395641d861ea019ca59 Mon Sep 17 00:00:00 2001 From: tristan Date: Fri, 13 Mar 2026 16:05:54 +0100 Subject: [PATCH] feat : ajout des frais kms + alignment du style de l'application --- .idea/SIRH.iml | 2 + .idea/php.xml | 2 + CLAUDE.md | 75 +++++ composer.json | 1 + composer.lock | 175 +++++++++++- frontend/components/AbsenceFormDrawer.vue | 25 +- frontend/components/AbsencePrintDrawer.vue | 11 +- frontend/components/AppDrawer.vue | 13 +- frontend/components/employees/ContractTab.vue | 36 +-- frontend/components/employees/MileageTab.vue | 268 ++++++++++++++++++ frontend/components/employees/RttTab.vue | 2 +- frontend/components/hours/HoursDayView.vue | 14 +- frontend/components/hours/HoursWeekView.vue | 8 +- frontend/composables/useEmployeeDetailPage.ts | 11 +- frontend/composables/useEmployeeMileage.ts | 73 +++++ frontend/i18n/locales/fr.json | 10 + frontend/pages/absence-types.vue | 69 ++--- frontend/pages/calendar.vue | 2 +- frontend/pages/employees/[id].vue | 32 ++- frontend/pages/sites.vue | 55 ++-- frontend/pages/users.vue | 50 +--- frontend/services/dto/mileage-allowance.ts | 9 + frontend/services/mileage-allowances.ts | 69 +++++ migrations/Version20260313125819.php | 29 ++ migrations/Version20260313133548.php | 26 ++ src/Entity/MileageAllowance.php | 192 +++++++++++++ src/Repository/MileageAllowanceRepository.php | 20 ++ src/State/MileageAllowanceDeleteProcessor.php | 42 +++ ...ileageAllowanceReceiptDownloadProvider.php | 53 ++++ ...MileageAllowanceReceiptUploadProcessor.php | 66 +++++ 30 files changed, 1264 insertions(+), 176 deletions(-) create mode 100644 CLAUDE.md create mode 100644 frontend/components/employees/MileageTab.vue create mode 100644 frontend/composables/useEmployeeMileage.ts create mode 100644 frontend/services/dto/mileage-allowance.ts create mode 100644 frontend/services/mileage-allowances.ts create mode 100644 migrations/Version20260313125819.php create mode 100644 migrations/Version20260313133548.php create mode 100644 src/Entity/MileageAllowance.php create mode 100644 src/Repository/MileageAllowanceRepository.php create mode 100644 src/State/MileageAllowanceDeleteProcessor.php create mode 100644 src/State/MileageAllowanceReceiptDownloadProvider.php create mode 100644 src/State/MileageAllowanceReceiptUploadProcessor.php diff --git a/.idea/SIRH.iml b/.idea/SIRH.iml index 47ac152..b6dc1e9 100644 --- a/.idea/SIRH.iml +++ b/.idea/SIRH.iml @@ -154,6 +154,8 @@ + + diff --git a/.idea/php.xml b/.idea/php.xml index c4734e1..6da05ea 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -155,6 +155,8 @@ + + diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..7ae0446 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,75 @@ +# SIRH + +## Mandatory Rules +- Any functional change MUST update `doc/` in the same intervention +- At the end of every feature addition or functional modification, update this CLAUDE.md to reflect new patterns, rules, or conventions introduced + +## Commands +- `make start` — start Docker stack +- `make test` — run backend tests (PHPUnit) +- `make dev-nuxt` — dev frontend +- `cd frontend && npm run build` — build frontend +- `php bin/console cache:clear && php bin/console cache:warmup` — clear cache after deploy + +## Stack +- Backend: Symfony + API Platform + Doctrine ORM +- Frontend: Nuxt 4 + Vue 3 + TypeScript + Tailwind CSS + +## Project Structure +- `src/` — Symfony domain, API resources, state providers/processors, services +- `frontend/` — Nuxt app (pages, components, composables, services) +- `migrations/` — Doctrine migrations (always include working `down()`) +- `doc/` — functional rules and business documentation + +## Functional Rules +- Reference: `doc/functional-rules.md` (mandatory reading before any business logic change) +- Complementary: `doc/leave-rollover.md`, `doc/rtt-rollover.md` + +## Domain Model +- Contracts: `trackingMode` (TIME=hours, PRESENCE=half-days), `weeklyHours` +- Contract types: FORFAIT, THIRTY_FIVE_HOURS, THIRTY_NINE_HOURS, INTERIM, CUSTOM +- Contract nature (per period): CDI, CDD, INTERIM +- Employee contract history: `employee_contract_periods`, resolved by `EmployeeContractResolver` +- Absences: stored per day (auto-split), AM/PM/full day, clear corresponding hour slots +- Absences with `countAsWorkedHours=true`: credit minutes (TIME) or nothing (PRESENCE) + +## Validation Rules +- `isValid` (RH): locks line for everyone (admin can only untoggle validation) +- `isSiteValid` (site manager): locks for non-admin, admin can still edit +- Any real modification resets both `isSiteValid=false` and `isValid=false` +- No-op saves preserve existing validations + +## Overtime Rules +- Contracts <= 35h: +25% from 35h to 43h, +50% beyond +- Contracts >= 39h: +25% from 39h to 43h, +50% beyond +- INTERIM: no overtime bonuses, no recovery time + +## Frontend Patterns + +### Table styling (standard across all pages) +- Header: `grid border border-black bg-tertiary-500 px-6 py-3 text-[20px] font-semibold text-black rounded-t-md sticky top-0 z-10` +- Body wrapper: `border-x border-b border-primary-500 rounded-b-md` +- Rows: `grid items-center gap-4 border-b border-primary-500 px-6 py-3 text-md font-bold text-primary-500 last:border-b-0 cursor-pointer hover:bg-tertiary-500` +- Page wrapper for scroll: `h-full flex flex-col overflow-hidden`, table container: `min-h-0 overflow-auto rounded-md bg-white` + +### Drawer buttons (AppDrawer) +- Edit mode: `grid grid-cols-2 gap-3` → Supprimer (red, left) + Modifier (primary, right) +- Create mode: centered `+ Ajouter` button, w-[200px] +- Exception: Users drawer has NO delete button +- All "Ajouter" buttons across the app use "+" prefix + +### API Platform (backend) +- Custom operations use Processor (write) / Provider (read) +- File uploads: `deserialize: false` on Post, access file via RequestStack +- Upload dir: `%kernel.project_dir%/var/uploads` + +## Backend Conventions +- Prefer explicit DTOs over associative arrays +- Business rules in backend (providers/processors/services), frontend is display/interaction only +- Keep backend PHP DTOs aligned with frontend TS DTOs (`frontend/services/dto/*`) +- Update unit tests when constructor/service signatures change + +## Language +- UI is in French +- User communicates in French +- Code (variables, comments) in English diff --git a/composer.json b/composer.json index c7ed2ef..f3e0a77 100644 --- a/composer.json +++ b/composer.json @@ -24,6 +24,7 @@ "symfony/flex": "^2", "symfony/framework-bundle": "8.0.*", "symfony/http-client": "8.0.*", + "symfony/mime": "8.0.*", "symfony/monolog-bundle": "^4.0", "symfony/property-access": "8.0.*", "symfony/property-info": "8.0.*", diff --git a/composer.lock b/composer.lock index cb7c9e7..0238fc4 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": "b540b6cb25ef55c5eebccb57c76da584", + "content-hash": "bdc04f5145303388bac52809ea3f4b05", "packages": [ { "name": "api-platform/doctrine-common", @@ -5374,6 +5374,92 @@ ], "time": "2026-01-28T10:46:31+00:00" }, + { + "name": "symfony/mime", + "version": "v8.0.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "5d26d1958aeeba2ace8cc64a3a93d4f5d8f8022b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/5d26d1958aeeba2ace8cc64a3a93d4f5d8f8022b", + "reference": "5d26d1958aeeba2ace8cc64a3a93d4f5d8f8022b", + "shasum": "" + }, + "require": { + "php": ">=8.4", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<5.2|>=7", + "phpdocumentor/type-resolver": "<1.5.1" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "league/html-to-markdown": "^5.0", + "phpdocumentor/reflection-docblock": "^5.2|^6.0", + "symfony/dependency-injection": "^7.4|^8.0", + "symfony/process": "^7.4|^8.0", + "symfony/property-access": "^7.4|^8.0", + "symfony/property-info": "^7.4|^8.0", + "symfony/serializer": "^7.4|^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v8.0.7" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-03-06T13:17:40+00:00" + }, { "name": "symfony/monolog-bridge", "version": "v8.0.4", @@ -5685,6 +5771,93 @@ ], "time": "2025-06-27T09:58:17+00:00" }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-10T14:38:51+00:00" + }, { "name": "symfony/polyfill-intl-normalizer", "version": "v1.33.0", diff --git a/frontend/components/AbsenceFormDrawer.vue b/frontend/components/AbsenceFormDrawer.vue index 580cb1d..ec25735 100644 --- a/frontend/components/AbsenceFormDrawer.vue +++ b/frontend/components/AbsenceFormDrawer.vue @@ -93,28 +93,29 @@ /> -
+
- +
+
+
diff --git a/frontend/components/AbsencePrintDrawer.vue b/frontend/components/AbsencePrintDrawer.vue index 0685439..e5e7683 100644 --- a/frontend/components/AbsencePrintDrawer.vue +++ b/frontend/components/AbsencePrintDrawer.vue @@ -96,17 +96,10 @@

-
- +
-
+
diff --git a/frontend/components/employees/ContractTab.vue b/frontend/components/employees/ContractTab.vue index 1706841..b92977f 100644 --- a/frontend/components/employees/ContractTab.vue +++ b/frontend/components/employees/ContractTab.vue @@ -1,7 +1,7 @@