From ee16779777673361c5d0c5e60f814d1772909a93 Mon Sep 17 00:00:00 2001 From: tristan Date: Fri, 20 Feb 2026 11:23:52 +0000 Subject: [PATCH] [#322] Page horaire (#4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit | Numéro du ticket | Titre du ticket | |------------------|-----------------| | #322 | Page horaire | ## Description de la PR [#322] Page horaire ## Modification du .env ## Check list - [ ] Pas de régression - [ ] TU/TI/TF rédigée - [ ] TU/TI/TF OK - [ ] CHANGELOG modifié Reviewed-on: https://gitea.malio.fr/MALIO-DEV/SIRH/pulls/4 Co-authored-by: tristan Co-committed-by: tristan --- .idea/SIRH.iml | 7 + AGENTS.md | 105 +++ config/services.yaml | 4 + frontend/components/AbsenceFormDrawer.vue | 8 +- frontend/components/CalendarGrid.vue | 79 +- .../components/EmployeeNameFilterInput.vue | 18 + frontend/components/SiteFilterSelector.vue | 25 + frontend/components/hours/HoursDayView.vue | 187 ++++ frontend/components/hours/HoursToolbar.vue | 213 +++++ frontend/components/hours/HoursWeekView.vue | 98 +++ frontend/components/hours/types.ts | 12 + frontend/components/ui/TimeSelect.vue | 151 ++++ frontend/composables/useApi.ts | 27 +- frontend/composables/useHoursPage.ts | 803 ++++++++++++++++++ frontend/layouts/auth.vue | 2 +- frontend/layouts/default.vue | 33 +- frontend/nuxt.config.ts | 13 +- frontend/package-lock.json | 77 ++ frontend/package.json | 1 + frontend/pages/absence-types.vue | 51 +- frontend/pages/calendar.vue | 122 +-- frontend/pages/employees.vue | 205 +++-- frontend/pages/hours.vue | 162 ++++ frontend/pages/login.vue | 6 +- frontend/pages/sites.vue | 2 +- frontend/pages/users.vue | 8 +- frontend/services/absence-types.ts | 4 +- frontend/services/auth.ts | 1 + frontend/services/contracts.ts | 13 + frontend/services/dto/absence-type.ts | 1 + frontend/services/dto/contract.ts | 25 + frontend/services/dto/employee.ts | 2 + frontend/services/dto/work-hour.ts | 81 ++ frontend/services/employees.ts | 16 +- frontend/services/work-hours.ts | 76 ++ frontend/utils/date.ts | 109 +++ frontend/utils/employee.ts | 31 + migrations/Version20260216100000.php | 31 + migrations/Version20260217161000.php | 34 + migrations/Version20260217162000.php | 28 + migrations/Version20260218120000.php | 54 ++ migrations/Version20260218183000.php | 30 + migrations/Version20260218190000.php | 26 + migrations/Version20260219180000.php | 83 ++ src/ApiResource/ScopedEmployee.php | 22 + src/ApiResource/WorkHourBulkUpsert.php | 39 + src/ApiResource/WorkHourBulkUpsertResult.php | 13 + src/ApiResource/WorkHourDayContext.php | 37 + src/ApiResource/WorkHourWeeklySummary.php | 32 + src/Doctrine/AbsenceCollectionExtension.php | 50 ++ src/Doctrine/WorkHourCollectionExtension.php | 53 ++ src/Dto/WorkHours/DayContextRow.php | 84 ++ src/Dto/WorkHours/WeeklyDaySummary.php | 19 + src/Dto/WorkHours/WeeklySummaryRow.php | 30 + src/Dto/WorkHours/WorkMetrics.php | 26 + src/Entity/Absence.php | 47 +- src/Entity/AbsenceType.php | 44 +- src/Entity/Contract.php | 122 +++ src/Entity/Employee.php | 24 +- src/Entity/WorkHour.php | 248 ++++++ src/Enum/ContractType.php | 47 + src/Enum/HalfDay.php | 11 + src/Enum/TrackingMode.php | 11 + src/Repository/AbsenceRepository.php | 102 +++ .../AbsenceReadRepositoryInterface.php | 32 + .../EmployeeScopedRepositoryInterface.php | 16 + .../WorkHourReadRepositoryInterface.php | 24 + src/Repository/EmployeeRepository.php | 104 +++ src/Repository/WorkHourRepository.php | 120 +++ src/Security/EmployeeScopeService.php | 99 +++ src/Security/Voter/AbsenceVoter.php | 48 ++ src/Security/Voter/WorkHourVoter.php | 50 ++ .../WorkHours/AbsenceSegmentsResolver.php | 50 ++ .../WorkHours/WorkedHoursCreditPolicy.php | 91 ++ src/State/AbsencePrintProvider.php | 57 +- src/State/AbsenceWriteProcessor.php | 223 +++++ src/State/ScopedEmployeeProvider.php | 29 + src/State/WorkHourBulkUpsertProcessor.php | 312 +++++++ src/State/WorkHourDayContextProvider.php | 110 +++ src/State/WorkHourWeeklySummaryProvider.php | 389 +++++++++ .../WorkHours/AbsenceSegmentsResolverTest.php | 61 ++ .../WorkHours/WorkedHoursCreditPolicyTest.php | 84 ++ tests/State/AbsenceWriteProcessorTest.php | 126 +++ .../State/WorkHourDayContextProviderTest.php | 154 ++++ .../WorkHourWeeklySummaryProviderTest.php | 170 ++++ 85 files changed, 6232 insertions(+), 242 deletions(-) create mode 100644 AGENTS.md create mode 100644 frontend/components/EmployeeNameFilterInput.vue create mode 100644 frontend/components/SiteFilterSelector.vue create mode 100644 frontend/components/hours/HoursDayView.vue create mode 100644 frontend/components/hours/HoursToolbar.vue create mode 100644 frontend/components/hours/HoursWeekView.vue create mode 100644 frontend/components/hours/types.ts create mode 100644 frontend/components/ui/TimeSelect.vue create mode 100644 frontend/composables/useHoursPage.ts create mode 100644 frontend/pages/hours.vue create mode 100644 frontend/services/contracts.ts create mode 100644 frontend/services/dto/contract.ts create mode 100644 frontend/services/dto/work-hour.ts create mode 100644 frontend/services/work-hours.ts create mode 100644 frontend/utils/employee.ts create mode 100644 migrations/Version20260216100000.php create mode 100644 migrations/Version20260217161000.php create mode 100644 migrations/Version20260217162000.php create mode 100644 migrations/Version20260218120000.php create mode 100644 migrations/Version20260218183000.php create mode 100644 migrations/Version20260218190000.php create mode 100644 migrations/Version20260219180000.php create mode 100644 src/ApiResource/ScopedEmployee.php create mode 100644 src/ApiResource/WorkHourBulkUpsert.php create mode 100644 src/ApiResource/WorkHourBulkUpsertResult.php create mode 100644 src/ApiResource/WorkHourDayContext.php create mode 100644 src/ApiResource/WorkHourWeeklySummary.php create mode 100644 src/Doctrine/AbsenceCollectionExtension.php create mode 100644 src/Doctrine/WorkHourCollectionExtension.php create mode 100644 src/Dto/WorkHours/DayContextRow.php create mode 100644 src/Dto/WorkHours/WeeklyDaySummary.php create mode 100644 src/Dto/WorkHours/WeeklySummaryRow.php create mode 100644 src/Dto/WorkHours/WorkMetrics.php create mode 100644 src/Entity/Contract.php create mode 100644 src/Entity/WorkHour.php create mode 100644 src/Enum/ContractType.php create mode 100644 src/Enum/HalfDay.php create mode 100644 src/Enum/TrackingMode.php create mode 100644 src/Repository/AbsenceRepository.php create mode 100644 src/Repository/Contract/AbsenceReadRepositoryInterface.php create mode 100644 src/Repository/Contract/EmployeeScopedRepositoryInterface.php create mode 100644 src/Repository/Contract/WorkHourReadRepositoryInterface.php create mode 100644 src/Repository/EmployeeRepository.php create mode 100644 src/Repository/WorkHourRepository.php create mode 100644 src/Security/EmployeeScopeService.php create mode 100644 src/Security/Voter/AbsenceVoter.php create mode 100644 src/Security/Voter/WorkHourVoter.php create mode 100644 src/Service/WorkHours/AbsenceSegmentsResolver.php create mode 100644 src/Service/WorkHours/WorkedHoursCreditPolicy.php create mode 100644 src/State/AbsenceWriteProcessor.php create mode 100644 src/State/ScopedEmployeeProvider.php create mode 100644 src/State/WorkHourBulkUpsertProcessor.php create mode 100644 src/State/WorkHourDayContextProvider.php create mode 100644 src/State/WorkHourWeeklySummaryProvider.php create mode 100644 tests/Service/WorkHours/AbsenceSegmentsResolverTest.php create mode 100644 tests/Service/WorkHours/WorkedHoursCreditPolicyTest.php create mode 100644 tests/State/AbsenceWriteProcessorTest.php create mode 100644 tests/State/WorkHourDayContextProviderTest.php create mode 100644 tests/State/WorkHourWeeklySummaryProviderTest.php diff --git a/.idea/SIRH.iml b/.idea/SIRH.iml index 6ff23a1..c7476c0 100644 --- a/.idea/SIRH.iml +++ b/.idea/SIRH.iml @@ -145,6 +145,13 @@ + + + + + + + diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..b277fe9 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,105 @@ +# AGENTS.md + +État des lieux opérationnel du projet SIRH (backend + frontend), à utiliser comme base sur les prochaines interventions. + +## 1) Stack et structure + +- Backend: Symfony + API Platform + Doctrine ORM +- Frontend: Nuxt 4 + Vue 3 + TypeScript + Tailwind +- Exécution locale: Docker via `makefile` + +Arborescence clé: +- `src/`: domaine, API resources, state providers/processors, services +- `tests/`: TU backend (PHPUnit) +- `frontend/`: app Nuxt (pages, composants, composables, services) +- `migrations/`: migrations Doctrine + +## 2) Commandes utiles + +- Démarrer stack: `make start` +- Tests backend: `make test` +- Build frontend: `cd frontend && npm run build` +- Dev frontend: `make dev-nuxt` + +## 3) Domaine métier (résumé) + +### Contrats +- Entité: `Contract` +- Champs principaux: `name`, `trackingMode`, `weeklyHours`, `isActive` +- `trackingMode`: + - `TIME`: suivi par heures + - `PRESENCE`: suivi présence demi-journées/journées +- Enums backend: + - `App\Enum\TrackingMode` + - `App\Enum\ContractType` (`FORFAIT`, `35H`, `39H`, `INTERIM`, `CUSTOM`) +- `Contract::getType()` est exposé en API (`contract:read`, `employee:read`) + +### Heures / absences +- Les absences sont découpées en enregistrements journaliers (pas de période unique stockée). +- Une ligne d’heures validée est verrouillée côté métier. +- Règles de crédit absence (`countAsWorkedHours=true`) gérées dans `WorkedHoursCreditPolicy`: + - contrats présence: crédit en unités de présence + - contrats temps: crédit en minutes selon règles contrat (35h, 39h, 4h, fallback) + +## 4) Écrans principaux + +### Page Heures (`frontend/pages/hours.vue`) +- Vue Jour + Vue Semaine (semaine réservée admin) +- Toolbar dédiée: `frontend/components/hours/HoursToolbar.vue` +- Vue jour: `frontend/components/hours/HoursDayView.vue` +- Vue semaine: `frontend/components/hours/HoursWeekView.vue` +- Logique page: `frontend/composables/useHoursPage.ts` + +### Points UX déjà en place +- Toolbar semaine: raccourcis semaine précédente / actuelle / suivante +- Légende absences affichée dans la toolbar (admin + vue semaine) +- Cellules semaine avec absence: couleur du type d’absence (plus rouge fixe) +- Pour user non-admin: restrictions d’édition selon validations/absences + +## 5) API / calculs hebdo + +- Provider: `src/State/WorkHourWeeklySummaryProvider.php` +- DTOs: + - `src/Dto/WorkHours/WeeklySummaryRow.php` + - `src/Dto/WorkHours/WeeklyDaySummary.php` +- Le résumé hebdo renvoie notamment: + - `trackingMode` + - `contractName` + - `contractType` + - détails journaliers (jour/nuit/total, présence, absence label/couleur) + +### Heures supp +- Règles métier: + - contrats <= 35h: tranche 25% de 35h à 43h, puis 50% au-delà + - contrats >= 39h: tranche 25% de 39h à 43h, puis 50% au-delà + - contrats `INTERIM`: pas de bonus 25/50 ni récup + +## 6) Conventions techniques + +- Favoriser DTO explicites plutôt que tableaux associatifs bruts. +- Utiliser les interfaces repository dans providers/processors testés. +- Centraliser les règles métier dans services/providers backend plutôt que dupliquer côté front. +- Front: éviter les calculs métier lourds; consommer les champs API déjà calculés. + +## 7) Tests et qualité + +- Les TU backend passent actuellement via `make test`. +- Le build frontend passe via `npm run build`. +- À chaque évolution métier: + - mettre à jour les tests provider/processor/service impactés + - maintenir la cohérence des DTO TypeScript (`frontend/services/dto/*`) + +## 8) Fichiers sensibles (à lire avant modif) + +- `src/State/WorkHourWeeklySummaryProvider.php` +- `src/Service/WorkHours/WorkedHoursCreditPolicy.php` +- `src/State/AbsenceWriteProcessor.php` +- `src/State/WorkHourBulkUpsertProcessor.php` +- `frontend/composables/useHoursPage.ts` +- `frontend/components/hours/HoursWeekView.vue` + +## 9) Décisions de conception actuelles + +- Les absences sont stockées par jour (facilite verrouillage/édition fine). +- Les règles de calcul (crédits, majorations, récup) sont portées côté backend. +- Le front reste centré sur l’affichage/interaction et réutilise les données enrichies de l’API. diff --git a/config/services.yaml b/config/services.yaml index 49aba49..9a7408a 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -22,5 +22,9 @@ services: App\: resource: '../src/' + App\Repository\Contract\AbsenceReadRepositoryInterface: '@App\Repository\AbsenceRepository' + App\Repository\Contract\EmployeeScopedRepositoryInterface: '@App\Repository\EmployeeRepository' + App\Repository\Contract\WorkHourReadRepositoryInterface: '@App\Repository\WorkHourRepository' + # add more service definitions when explicit configuration is needed # please note that last definitions always *replace* previous ones diff --git a/frontend/components/AbsenceFormDrawer.vue b/frontend/components/AbsenceFormDrawer.vue index 8535acb..580cb1d 100644 --- a/frontend/components/AbsenceFormDrawer.vue +++ b/frontend/components/AbsenceFormDrawer.vue @@ -9,6 +9,7 @@ id="employee" v-model="absenceForm.employeeId" :class="employeeFieldClass" + :disabled="props.lockEmployee" >