113 lines
6.7 KiB
Markdown
113 lines
6.7 KiB
Markdown
# SIRH
|
|
|
|
## Mandatory Rules
|
|
- Any functional change MUST update `doc/` in the same intervention
|
|
- Any functional change MUST update the in-app documentation (`frontend/data/documentation-content.ts`) 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)
|
|
- Driver periods (`isDriver=true` on `EmployeeContractPeriod`): separate screen `/driver-hours`, uses `dayHoursMinutes`/`nightHoursMinutes` + meal/overnight flags on `WorkHour`
|
|
|
|
## 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
|
|
- CUSTOM contracts (weeklyHours ≠ 35 and ≠ 39, not INTERIM/FORFAIT): reference = actual contractual hours, no 25%/50% bonuses (1h overtime = 1h recovery), deficit doesn't impact balance
|
|
- INTERIM: no overtime bonuses, no recovery time
|
|
- Driver contracts: RTT uses `dayHoursMinutes + nightHoursMinutes + workshopHoursMinutes` instead of morning/afternoon/evening time ranges
|
|
- FORFAIT weekend/holiday bonus: each weekend or public holiday day worked gives bonus leave (full day if morning+afternoon, 0.5 if only one). Added to acquired days, no cap. PRESENCE mode only.
|
|
|
|
## Frais (MileageAllowance)
|
|
- Onglet "Frais" (anciennement "Frais Kms") sur la fiche employé
|
|
- Validation: mois obligatoire + au moins `kilometers > 0` ou `amount > 0`
|
|
- Les deux champs km et montant sont optionnels individuellement mais au moins un requis
|
|
|
|
## Formations
|
|
- Onglet "Formation" sur la fiche employé (admin uniquement)
|
|
- Champs : date début, date fin, justificatif PDF optionnel, commentaire
|
|
- Validation: dates obligatoires, `endDate >= startDate`, fichier PDF uniquement
|
|
- Justificatif stocké dans `var/uploads/formations/{année}/{mois}/{uuid}.pdf` (année/mois = startDate)
|
|
- Suppression et remplacement du justificatif nettoient l'ancien fichier disque
|
|
- Tri tableau par `startDate DESC`
|
|
- Affichage écran Heures (jour) : pill "Formation" (indigo) dans la colonne Absence. Quand une formation existe, le bouton "Modifier" de la colonne Absence est masqué (lockdown complet du jour pour la gestion d'absence)
|
|
- Affichage Calendrier : cellule "F" (indigo) si formation seule, ou icône école en coin si formation + absence. Cellules avec formation non cliquables. Légende dédiée. PDF export : code "F" indigo ou astérisque à côté du code d'absence
|
|
- Le CRUD formation est exclusivement géré depuis la fiche employé > onglet Formation
|
|
|
|
## 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`
|
|
|
|
## Audit Logging
|
|
- All processors that modify entities impacting calculations (heures, absences, contrats, RTT) MUST inject `AuditLogger` and log create/update/delete actions
|
|
- `AuditLogger::log()` persists without flushing — the processor's `flush()` handles both the data change and the audit entry atomically
|
|
- Audit logs are accessible only via `ROLE_SUPER_ADMIN` (hidden role, added manually in DB)
|
|
- Documentation: `doc/audit-logging.md`
|
|
|
|
## 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
|
|
|
|
## In-App Documentation
|
|
- Content: `frontend/data/documentation-content.ts` — structured TypeScript data with all user-facing documentation
|
|
- Types: `frontend/types/documentation.ts` — DocSection, DocArticle, DocBlock
|
|
- Composable: `frontend/composables/useDocumentation.ts` — role-based filtering (employee < site_manager < admin)
|
|
- Components: `frontend/components/documentation/` — DocumentationPage, DocumentationSection, DocumentationArticle
|
|
- Page: `frontend/pages/documentation.vue`
|
|
- 3 access levels: `employee` (ROLE_SELF), `site_manager` (ROLE_USER), `admin` (ROLE_ADMIN) — cumulative (admin sees everything)
|
|
- Each section/article has a `requiredLevel` that controls visibility
|
|
- When adding or modifying a feature, update the corresponding section in `documentation-content.ts`
|
|
|
|
## Language
|
|
- UI is in French
|
|
- User communicates in French
|
|
- Code (variables, comments) in English
|