docs(rtt) : implementation plan + spec fix (workDaysHours neutralisation) for solidarity deficit
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -81,16 +81,22 @@ un jour de solidarité `S` tombe dans la semaine **et** a été inclus dans le s
|
||||
|
||||
```
|
||||
$contractAtS = $employeeContractsByDate[$S] ?? null;
|
||||
if ($contractAtS est CUSTOM && $contractAtS->getWeeklyHours() < 35) {
|
||||
$isoDayS = (int) (new DateTimeImmutable($S))->format('N');
|
||||
$refS = $this->resolveDailyReferenceMinutes($contractAtS->getWeeklyHours(), $isoDayS);
|
||||
$workedS = $dailyWorkedMinutes[$S]; // déjà calculé dans la boucle des jours
|
||||
$prorata = (int) round($contractAtS->getWeeklyHours() * 12);
|
||||
$weeklyHours = $contractAtS?->getWeeklyHours();
|
||||
$typeAtS = ContractType::resolve($contractAtS?->getName(), $contractAtS?->getTrackingMode(), $weeklyHours);
|
||||
|
||||
// 1) neutraliser le net naturel du jour (annule worked - ref, même fonction de
|
||||
// référence que computeWeeklyCustomReferenceMinutes → annulation exacte)
|
||||
// 2) appliquer le forfait
|
||||
$weeklyOvertimeTotalMinutes += $refS - $workedS - $prorata;
|
||||
if (ContractType::CUSTOM === $typeAtS && null !== $weeklyHours && $weeklyHours < 35) {
|
||||
$isoDayS = (int) (new DateTimeImmutable($S))->format('N');
|
||||
$workDaysForS = $workDaysByDate[$employeeId][$S] ?? null; // {iso_day: minutes}
|
||||
// Heures contractuelles RÉELLES du jour (planning workDaysHours), PAS la
|
||||
// répartition uniforme weeklyHours/5 — c'est ce qui rend le net = -prorata.
|
||||
$expectedS = $this->dailyReferenceResolver->resolve($weeklyHours, $isoDayS, $workDaysForS);
|
||||
$workedS = $dailyWorkedMinutes[$S]; // déjà calculé dans la boucle des jours
|
||||
$prorata = (int) round($weeklyHours * 12);
|
||||
|
||||
// 1) faire compter le jour comme s'il était travaillé normalement (annule la
|
||||
// valeur réelle du jour, quelle qu'elle soit : RTT posé, heures, vide, crédit
|
||||
// férié virtuel) ; 2) appliquer le forfait solidarité.
|
||||
$weeklyOvertimeTotalMinutes += ($expectedS - $workedS) - $prorata;
|
||||
}
|
||||
```
|
||||
|
||||
@@ -98,10 +104,20 @@ Puis `buildWeekRecoveryDetail(...)` est appelé tel quel : pour un CUSTOM,
|
||||
`totalMinutes = overtimeMinutes = weeklyOvertimeTotalMinutes` (signé), bandes 25/50 = 0,
|
||||
`isFlatRecovery = true`.
|
||||
|
||||
> Note : la référence `$refS` doit être calculée avec la **même** fonction que
|
||||
> `computeWeeklyCustomReferenceMinutes` (`resolveDailyReferenceMinutes(weeklyHours, isoDay)`)
|
||||
> pour que la neutralisation annule exactement la contribution du jour, quelle que soit la
|
||||
> façon dont la référence journalière est répartie.
|
||||
> **Pourquoi `workDaysHours` et pas la référence hebdo CUSTOM** : la référence CUSTOM
|
||||
> (`computeWeeklyCustomReferenceMinutes`) répartit `weeklyHours` uniformément sur les 5
|
||||
> jours ouvrés (`weeklyHours/5`), sans tenir compte du planning réel. Neutraliser le jour
|
||||
> avec cette valeur uniforme (48 min pour le lundi d'Ewa) laisserait le manque des autres
|
||||
> jours → −2h au lieu de −48 min. En neutralisant avec l'attendu RÉEL du jour
|
||||
> (`workDaysHours[lundi] = 120 min`), le terme `(attendu − travaillé)` ramène la semaine à
|
||||
> son net « normal » (0 pour une semaine pleine), puis le forfait applique exactement
|
||||
> −prorata. `DailyReferenceMinutesResolver::resolve(weeklyHours, isoDay, workDaysMinutes)`
|
||||
> renvoie déjà cet attendu réel quand `workDaysMinutes` est fourni (obligatoire pour tout
|
||||
> CUSTOM < 35h). Fallback uniforme si absent.
|
||||
>
|
||||
> **Robustesse `EXCLUDED` / férié** : `(attendu − travaillé)` annule n'importe quelle
|
||||
> valeur de `$workedS`, y compris un éventuel crédit férié virtuel si le Lundi de Pentecôte
|
||||
> cessait d'être exclu. Le résultat ne dépend donc pas de l'état d'`EXCLUDED_PUBLIC_HOLIDAYS`.
|
||||
|
||||
## Cas limites
|
||||
|
||||
|
||||
Reference in New Issue
Block a user