Commit Graph

304 Commits

Author SHA1 Message Date
tristan 06e462ef31 feat(audit) : pagination défaut 10 + filtres employé/utilisateur en select
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 11:52:20 +02:00
tristan e6a84af9b5 docs(audit) : documente la refonte de l'écran journal 2026-06-24 11:30:36 +02:00
tristan 04517bf1a6 fix(audit) : importe onMounted explicitement dans l'écran journal
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 11:29:41 +02:00
tristan 34ed3d0222 feat(audit) : refonte écran journal (MalioDataTable + drawers filtre & détail)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 11:26:20 +02:00
tristan 32b1af2377 feat(audit) : composable useAuditLogsList (filtres brouillon/appliqué + pagination) 2026-06-24 11:22:53 +02:00
tristan 60fea783c0 feat(audit) : étend AuditLogFilters (multi-type/action, user/ip/appareil, perPage) 2026-06-24 11:20:18 +02:00
tristan 4c46b2b32c feat(audit) : filtres journal enrichis (utilisateur/ip/appareil, multi-type/action, perPage) 2026-06-24 11:16:58 +02:00
tristan 2d284b897b docs : plan refonte écran journal (MalioDataTable + drawers)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 11:14:40 +02:00
tristan c9fd973da3 docs : spec refonte écran journal (MalioDataTable + drawer filtre)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 11:03:36 +02:00
tristan 39cdfd7428 docs(audit) : note la dépendance CORS de X-Device-Id
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 10:50:03 +02:00
tristan 95bf8c4c0a fix(audit) : autorise l'en-tête X-Device-Id en CORS (débloque le front)
Le front envoie X-Device-Id sur toutes les requêtes (cross-origin :3001 -> :8081).
Sans l'ajouter à allow_headers, le préflight CORS échoue et le navigateur bloque
toutes les requêtes API. Vérifié : préflight OPTIONS passe de 400 à 200.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 10:49:04 +02:00
tristan 8c1cd6704e test(audit) : utilise createStub pour une sortie PHPUnit propre
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 10:37:12 +02:00
tristan 48ee173461 refactor(audit) : alias explicite + borne le user-agent stocké
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 10:34:03 +02:00
tristan 4513896112 docs(audit) : documente le contexte forensique du journal 2026-06-24 10:29:54 +02:00
tristan d44759eb14 docs(audit) : documente trusted_proxies pour l'IP du journal 2026-06-24 10:27:53 +02:00
tristan cc9b50a765 feat(audit) : envoie un device id persistant sur les requêtes API 2026-06-24 10:25:50 +02:00
tristan 62dcae1879 feat(audit) : expose le contexte forensique dans l'API lecture 2026-06-24 10:20:27 +02:00
tristan 003835463b feat(audit) : capture IP/appareil/user-agent dans AuditLogger 2026-06-24 10:15:58 +02:00
tristan 9f0e624138 feat(audit) : colonnes contexte forensique sur audit_logs 2026-06-24 10:13:39 +02:00
tristan 3939ea75e5 feat(audit) : ajoute UserAgentParser (libellé appareil lisible) 2026-06-24 10:10:58 +02:00
tristan 025ce8a367 docs : plan implémentation contexte forensique journal
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 10:09:09 +02:00
tristan 3510d5253d docs : spec contexte forensique journal d'activité
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 10:01:36 +02:00
gitea-actions c119db0b02 chore: bump version to v0.1.123
Auto Tag Develop / tag (push) Successful in 7s
Build & Push Docker Image / build (push) Successful in 46s
v0.1.123
2026-06-24 07:44:43 +00:00
tristan a52c35e082 fix: Malio UI (#32)
Auto Tag Develop / tag (push) Successful in 12s
| Numéro du ticket | Titre du ticket |
|------------------|-----------------|
|                  |                 |

## Description de la PR

## Modification du .env

## Check list

- [ ] Pas de régression
- [ ] TU/TI/TF rédigée
- [ ] TU/TI/TF OK
- [ ] CHANGELOG modifié

Reviewed-on: #32
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
2026-06-24 07:44:30 +00:00
gitea-actions a1af125c78 chore: bump version to v0.1.122
Auto Tag Develop / tag (push) Successful in 9s
Build & Push Docker Image / build (push) Successful in 2m6s
v0.1.122
2026-06-24 07:16:54 +00:00
tristan 8e59e9fd6a fix(heures) : n'enregistrer que les lignes modifiées (anti-écrasement concurrent) (#31)
Auto Tag Develop / tag (push) Successful in 10s
## Problème

Sur l'écran **Heures** / **Heures Conducteurs**, l'enregistrement envoyait au bulk-upsert une entrée pour **tous** les employés visibles non verrouillés, à partir de l'état en mémoire de la grille. Le backend (`WorkHourBulkUpsertProcessor`) traitant une **entrée vide comme une suppression**, un admin avec une grille **périmée** pouvait supprimer une ligne saisie entre-temps par un autre utilisateur.

### Scénario reproduit
1. Un admin ouvre l'écran ; la ligne d'un salarié `ROLE_SELF` est vide.
2. Ce salarié saisit ses heures dans sa propre session → ligne créée, **non validée** (donc non verrouillée).
3. L'admin, sur sa grille périmée, enregistre d'autres employés.
4. Le payload contient une entrée **vide** pour le salarié → le backend supprime sa ligne. **Perte de données.**

## Correctif (suivi des lignes modifiées)

`hydrateRows` capture un instantané `loadedRows` de l'état chargé depuis le serveur. `handleSave` ne transmet plus que les lignes **dont l'état courant diffère de l'instantané**.

- Ligne **intouchée** → jamais envoyée → jamais supprimée 
- Ligne **vidée volontairement** → envoyée vide → supprimée (métier conservé)
- Ligne **remplie/modifiée** → envoyée → créée/mise à jour

Symétrique dans `useHoursPage.ts` et `useDriverHoursPage.ts`.

## Limite connue
Pas de verrou optimiste backend : l'édition **explicite** d'une ligne sur données périmées peut toujours écraser une saisie concurrente sur cette même ligne (hors périmètre).

## Doc
- `doc/hours-save-dirty-tracking.md` (nouveau)
- Note `CLAUDE.md` (section *Validation Rules*)

## Vérification
- Pre-commit hook : **236 tests PHPUnit OK**.
- Pas de harnais de tests frontend (revue de code uniquement).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: #31
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
2026-06-24 07:16:42 +00:00
gitea-actions 4d4bdba914 chore: bump version to v0.1.121
Auto Tag Develop / tag (push) Successful in 6s
Build & Push Docker Image / build (push) Successful in 59s
v0.1.121
2026-06-16 13:53:14 +00:00
tristan 74abecbe03 feat(heures) : calendrier des jours validés (vue Jour) + harmonisation Malio UI (#30)
Auto Tag Develop / tag (push) Successful in 10s
## Fonctionnel
- Calendrier MalioDate en vue Jour (écrans Heures ET Heures Conducteurs) : les jours entièrement validés par un admin sont peints en vert.
  - Endpoint `GET /work-hours/validation-status?from=&to=[&driver=1]` (scope conducteur inversé via `driver=1`), périmètre complet (ignore le filtre sites).
  - Chargement à la volée par mois (event `@month-change`), refresh après validation / saisie / absence.

## Harmonisation @malio/layer-ui 1.7.11
- `reserveMessageSpace=false` sur tous les champs (alignement).
- Tous les drawers migrés sur `MalioDrawer` (titre via slot `#header`, `AppDrawer` custom supprimé).
- Boutons d'action en `MalioButton` ; deux boutons côte à côte partagent l'espace.
- Inputs date en `MalioDate`, sélecteur semaine en `MalioDateWeek`.
- Boutons d'ajout uniformisés sur « Ajouter » + icône.

## Divers
- `.env` : `EXCLUDED_PUBLIC_HOLIDAYS="null"`.
- Doc : `doc/hours-validated-days.md`, `documentation-content.ts`, `CLAUDE.md`.
- Tests : provider `WorkHourValidationStatus` (suite complète 236/236 OK via pre-commit hook).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: #30
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
2026-06-16 13:53:03 +00:00
gitea-actions 5d2b5d1c54 chore: bump version to v0.1.120
Auto Tag Develop / tag (push) Successful in 7s
Build & Push Docker Image / build (push) Successful in 37s
v0.1.120
2026-06-12 13:06:07 +00:00
tristan c8e7f80c72 fix(conges) : un congé posé un dimanche n'est plus décompté (récap salaire)
Auto Tag Develop / tag (push) Successful in 11s
Le récap salaire comptait les congés (C) tombant un dimanche via
countAbsencesByCode, alors que l'onglet Congés, le rollover et les jours de
présence l'ignoraient déjà. Garde ajoutée (C + dimanche → ignoré) pour aligner :
poser une période à cheval sur un week-end (ex. jeu→mar) ne fait plus perdre le
dimanche. Correctif au comptage uniquement : les lignes d'absence du dimanche
restent créées et affichées sur le calendrier (volonté RH), l'existant cesse de
compter sans migration. Périmètre strict : code C (maladie/AT inchangés), samedi
inchangé (budget dédié).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 15:03:49 +02:00
gitea-actions c298f66993 chore: bump version to v0.1.119
Auto Tag Develop / tag (push) Successful in 9s
Build & Push Docker Image / build (push) Successful in 41s
v0.1.119
2026-06-12 12:40:10 +00:00
tristan 7187989003 feat(heures) : affichage des jours travaillés (CUSTOM) sur la vue Jour
Auto Tag Develop / tag (push) Successful in 12s
Le libellé sous le nom de l'employé affiche en suffixe les jours du planning
workDaysHours au format court (ex. BUREAU — CDI — LU,JE) pour les contrats CUSTOM.
Résolu à la date filtrée et exposé via WorkHourDayContext.workDaysHours ; formaté
front par formatWorkedDaysShort. Limité aux CUSTOM (35h/39h/forfait/intérim sans
planning → rien affiché) et à l'écran Heures (pas Heures Conducteurs).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 14:33:46 +02:00
gitea-actions 4b22270c60 chore: bump version to v0.1.118
Auto Tag Develop / tag (push) Successful in 8s
Build & Push Docker Image / build (push) Successful in 1m4s
v0.1.118
2026-06-12 09:58:49 +00:00
tristan acbf1ccecb fix(rtt) : jour de solidarité sans déficit si le salarié ne travaille pas le lundi
Auto Tag Develop / tag (push) Successful in 11s
Un contrat CUSTOM < 35h qui ne travaille pas le lundi (jour de solidarité,
workDaysHours[lundi] absent → attendu = 0) ne portait à tort un déficit
forfaitaire ((0 − 0) − prorata = −prorata). Garde ajoutée : aucun déficit
quand expectedMinutes === 0. Ewa (Lun+Jeu) reste à −0h48 ; Nadia (Mar+Ven)
passe de −0h48 à 0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 11:01:24 +02:00
gitea-actions 036399846b chore: bump version to v0.1.117
Auto Tag Develop / tag (push) Successful in 5s
Build & Push Docker Image / build (push) Successful in 34s
v0.1.117
2026-06-12 07:45:41 +00:00
tristan 0a9b26d31e feat(overtime-contingent) : heures supp structurelles (>35h) ajoutées au contingent
Auto Tag Develop / tag (push) Successful in 6s
Les heures contractuelles au-delà de 35h (ex. 39h → 17,33h décimales = 17h20/mois)
sont payées chaque mois sans transiter par les paiements RTT (référence 39h). Elles
manquaient au contingent. Ajout via StructuralOvertimeContingentCalculator :
(weeklyHours-35)×260 min/mois, généralisé aux contrats non-forfait/non-intérim >35h,
proratisé aux jours sous contrat. Branché sur l'encart fiche et l'export PDF.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 08:57:26 +02:00
gitea-actions 7dc73f37ac chore: bump version to v0.1.116
Auto Tag Develop / tag (push) Successful in 8s
Build & Push Docker Image / build (push) Successful in 27s
v0.1.116
2026-06-12 06:22:33 +00:00
tristan dc02316d8b Merge remote-tracking branch 'origin/develop' into develop
Auto Tag Develop / tag (push) Successful in 12s
2026-06-12 08:21:57 +02:00
gitea-actions e89a1fd7cf chore: bump version to v0.1.115
Auto Tag Develop / tag (push) Successful in 6s
Build & Push Docker Image / build (push) Successful in 34s
v0.1.115
2026-06-11 15:48:00 +00:00
tristan 327c10fda4 feat(overtime-contingent) : contingent d'heures supplémentaires payées (#29)
Auto Tag Develop / tag (push) Successful in 7s
## Résumé
Suivi par **année civile** (Janv–Déc) des heures supplémentaires payées des employés non-forfait (chauffeurs inclus) face au plafond légal (**350 h** chauffeurs / **220 h** autres).

- **Fiche employé** : encart header `Total H.payés {année} : X h / plafond h` (année civile courante, rouge si dépassement), via `GET /employees/{id}/overtime-contingent`.
- **Export PDF** `GET /overtime-contingent/print?year=&siteIds=` (ROLE_USER, périmètre `findScoped`) : groupé par site, colonnes Janv–Déc + colonne `Total payé / payable`. Drawer liste employés (année + sites).
- Heures payées = `base25 + base50` (hors majoration). Mapping exercice→civil : `mois ≥ 6 ? exercice−1 : exercice`.
- Cœur partagé pur `OvertimePaidContingentCalculator`.
- Ajout « Année civile » dans le titre des deux exports PDF (contingent H.supp. et heures de nuit).

## Tests
- 214 tests PHPUnit verts (calculateur : mapping civil, base-only, plafond ; builder : ventilation mensuelle, ligne à zéro).

## Hors périmètre (consigné)
- Bug latent `SalaryRecapPrintProvider` : rattachement des paiements RTT des mois Juin–Déc par année civile sur un stockage par exercice. À traiter séparément.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: #29
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
2026-06-11 15:47:19 +00:00
tristan 6ba70c36e9 docs(overtime-contingent) : plan d'implémentation contingent heures supp payées
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 16:55:00 +02:00
tristan ef15d96d2a docs(overtime-contingent) : spec contingent heures supp payées
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 16:49:02 +02:00
gitea-actions ceba1121f0 chore: bump version to v0.1.114
Auto Tag Develop / tag (push) Successful in 6s
Build & Push Docker Image / build (push) Successful in 37s
v0.1.114
2026-06-11 13:02:39 +00:00
tristan b5bd4db5f1 feat(heures) : export Contingent heures de nuit (liste employés) (#28)
Auto Tag Develop / tag (push) Successful in 9s
## Résumé
Nouvel export PDF **Contingent heures de nuit** dans le drawer Export de la liste employés.

- PDF **A4 paysage** : lignes = employés (groupés par site, triés displayOrder/nom/prénom), colonnes = 12 mois civils, chaque mois avec 2 sous-colonnes **H.nuit** et **N.jours**.
- Heures de nuit = minutes dans la fenêtre **21h→6h** via un service partagé `NightHoursCalculator` (mutualisé avec `WorkHourWeeklySummaryProvider` et `YearlyHoursExportBuilder` — duplication supprimée, sans changement de comportement).
- **Conducteurs inclus** via `WorkHour.nightHoursMinutes`. Statut conducteur résolu par date.
- **N.jours** = nb de jours où les minutes de nuit ≥ 240 (4h). Aucun crédit absence/férié.
- Périmètre via `EmployeeRepository::findScoped` (admin → tous, chef de site → ses sites), endpoint `GET /night-hours-contingent/print?year=YYYY` (`ROLE_USER`).
- Sélecteur d'année (année civile). Colonne Nom calibrée, séparateurs de mois épais.

## Composants
- Service `NightHoursCalculator`, builder `NightContingentExportBuilder`, DTO `NightContingentRow`
- Provider `NightHoursContingentPrintProvider` + opération API `NightHoursContingentPrint`
- Gabarit `templates/night-hours-contingent/print.html.twig`
- Option frontend dans `frontend/pages/employees/index.vue`
- Docs : `doc/functional-rules.md`, `CLAUDE.md`, `frontend/data/documentation-content.ts`

## Tests
- Nouveaux tests unitaires : `NightHoursCalculatorTest` (fenêtre 21h→6h, passage minuit, bornes), `NightContingentExportBuilderTest` (agrégation mensuelle, règle ≥4h=1j, conducteur, cas sans heures)
- Suite complète : **208 tests OK**
- Rendu PDF validé visuellement (Twig→Dompdf)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: #28
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
2026-06-11 13:02:30 +00:00
gitea-actions 49ad6306ea chore: bump version to v0.1.113
Auto Tag Develop / tag (push) Successful in 8s
Build & Push Docker Image / build (push) Successful in 1m9s
v0.1.113
2026-06-11 08:46:19 +00:00
tristan 9d2e70f81e feat(recap-conges) : cutoff S-1 au lieu de S-2
Auto Tag Develop / tag (push) Successful in 13s
Le récap des congés se fige désormais à la fin de la semaine précédente
(S-1) au lieu de l'avant-dernière (S-2), incluant ainsi une semaine de
plus. Demande métier.

- LeaveRecapCutoff : -14j -> -7j
- Test unitaire figeant la règle S-1
- Doc fonctionnelle, doc in-app et CLAUDE.md mis à jour

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 10:45:33 +02:00
gitea-actions 370bbb491f chore: bump version to v0.1.112
Auto Tag Develop / tag (push) Successful in 6s
Build & Push Docker Image / build (push) Failing after 28s
v0.1.112
2026-06-11 08:37:05 +00:00
tristan f0387233e4 [#SIRH-36] corriger calcule rtt contrat custom (#27)
Auto Tag Develop / tag (push) Successful in 7s
| Numéro du ticket | Titre du ticket |
|------------------|-----------------|
|                  |                 |

## Description de la PR

## Modification du .env

## Check list

- [ ] Pas de régression
- [ ] TU/TI/TF rédigée
- [ ] TU/TI/TF OK
- [ ] CHANGELOG modifié

Reviewed-on: #27
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
2026-06-11 08:36:57 +00:00
gitea-actions 081d92b9f4 chore: bump version to v0.1.111
Auto Tag Develop / tag (push) Successful in 7s
Build & Push Docker Image / build (push) Successful in 3m38s
v0.1.111
2026-06-11 06:36:10 +00:00
tristan 143278a368 feat(heures) : export PDF jour accessible aux chefs de site (périmètre par site)
Auto Tag Develop / tag (push) Successful in 10s
L'export des heures de la vue Jour était réservé aux admins. Il est désormais
ouvert aux chefs de site, restreint à leurs sites :
- sécurité endpoint ROLE_ADMIN -> ROLE_USER
- périmètre résolu côté backend via EmployeeRepository::findScoped() (un siteIds
  hors périmètre est ignoré, aucune fuite inter-sites)
- bouton Exporter visible pour admin + chef de site (masqué pour ROLE_SELF)
- doc, doc in-app et CLAUDE.md mis à jour

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-11 08:31:30 +02:00