Gestion du changement de type de contrat + correction du calcule des RTT sur un contrat qui commence en milieu de semaine (#19)
Auto Tag Develop / tag (push) Has been cancelled

| Numéro du ticket | Titre du ticket |
|------------------|-----------------|
|                  |                 |

## Description de la PR

## Modification du .env

## Check list

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

Reviewed-on: #19
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
This commit was merged in pull request #19.
This commit is contained in:
2026-05-22 06:42:33 +00:00
committed by Autin
parent b541f9ded8
commit abdaf809f8
40 changed files with 5021 additions and 153 deletions
@@ -221,8 +221,9 @@ final readonly class RttRecoveryComputationService
continue;
}
$weekAnchorNature = $naturesByDate[$employeeId][$weekDays[0]] ?? ContractNature::CDI;
$weekAnchorContract = $employeeContractsByDate[$weekDays[0]] ?? null;
$weekAnchorDate = $this->resolveWeekAnchorDate($weekDays, $employeeContractsByDate);
$weekAnchorNature = $naturesByDate[$employeeId][$weekAnchorDate] ?? ContractNature::CDI;
$weekAnchorContract = $employeeContractsByDate[$weekAnchorDate] ?? null;
$isWeekPresenceTracking = TrackingMode::PRESENCE->value === $weekAnchorContract?->getTrackingMode();
$disableOvertimeBonuses = $this->hasDisabledOvertimeBonuses($weekAnchorContract, $weekAnchorNature);
$weekContractType = ContractType::resolve(
@@ -387,6 +388,27 @@ final readonly class RttRecoveryComputationService
return $total;
}
/**
* Date d'ancrage de la semaine pour résoudre le type/nature de contrat : premier jour
* de la semaine couvert par un contrat. Évite qu'une semaine d'embauche en milieu de
* semaine (premiers jours hors contrat) soit classée CUSTOM — ce qui désactiverait à
* tort les bonus 25 %/50 % d'un contrat 35h/39h. Fallback sur le 1er jour si aucun jour
* n'est contracté (semaine entièrement hors contrat → 0 de toute façon).
*
* @param list<string> $weekDays
* @param array<string, ?Contract> $contractsByDate
*/
private function resolveWeekAnchorDate(array $weekDays, array $contractsByDate): string
{
foreach ($weekDays as $date) {
if (null !== ($contractsByDate[$date] ?? null)) {
return $date;
}
}
return $weekDays[0];
}
/**
* @param list<string> $days
* @param array<string, ?Contract> $contractsByDate
@@ -413,10 +435,17 @@ final readonly class RttRecoveryComputationService
{
$total = 0;
foreach ($days as $date) {
$isoDay = (int) new DateTimeImmutable($date)->format('N');
$contract = $contractsByDate[$date] ?? null;
$hours = $contract?->getWeeklyHours();
$startHours = (null !== $hours && $hours >= 39) ? 39 : 35;
$isoDay = (int) new DateTimeImmutable($date)->format('N');
$contract = $contractsByDate[$date] ?? null;
$hours = $contract?->getWeeklyHours();
// Days without an active contract (pre-hire, post-termination, contract
// gaps) must NOT contribute to the weekly 25% overtime threshold —
// otherwise hiring mid-week artificially inflates the threshold and
// erases legitimate overtime.
if (null === $hours || $hours <= 0) {
continue;
}
$startHours = $hours >= 39 ? 39 : 35;
$total += $this->resolveDailyReferenceMinutes($startHours, $isoDay);
}