fix(absences) : demi-journée mono-jour décomptée 0,5 (et non 0)

Sur une demande d'un seul jour, le formulaire recopie la demi-journée de
début sur la fin (même date), si bien que les deux bornes portaient une
demi-journée et 0,5 était soustrait deux fois (1 - 0,5 - 0,5 = 0).

Quand start et end tombent le même jour, les deux bornes se confondent :
on ne soustrait désormais 0,5 qu'une seule fois. Comparaison par
getTimestamp() pour rester compatible strict_comparison (=== sur deux
DateTimeImmutable distincts teste l'identité d'instance, pas la valeur).

Couverture complétée : mono-jour plein, week-end, férié, inversion de
dates, demi-journée de fin seule, demi sur samedi en mode ouvrables.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Matthieu
2026-05-26 10:05:42 +02:00
parent 65df36dd1a
commit 45e86543a1
2 changed files with 89 additions and 5 deletions
+13 -5
View File
@@ -54,11 +54,19 @@ final readonly class AbsenceDayCalculator
// A half-day only subtracts 0.5 when its boundary day is actually
// counted (otherwise a half-day posted on a weekend/holiday would
// wrongly under-count the absence).
if (null !== $startHalfDay && $this->isCountedDay($start, $workingDaysOnly)) {
$days -= 0.5;
}
if (null !== $endHalfDay && $this->isCountedDay($end, $workingDaysOnly)) {
$days -= 0.5;
if ($start->getTimestamp() === $end->getTimestamp()) {
// Single-day request: both boundaries collapse onto the same day,
// so a half-day must subtract 0.5 once, never twice.
if ((null !== $startHalfDay || null !== $endHalfDay) && $this->isCountedDay($start, $workingDaysOnly)) {
$days -= 0.5;
}
} else {
if (null !== $startHalfDay && $this->isCountedDay($start, $workingDaysOnly)) {
$days -= 0.5;
}
if (null !== $endHalfDay && $this->isCountedDay($end, $workingDaysOnly)) {
$days -= 0.5;
}
}
return max(0.0, $days);