diff --git a/src/Service/WorkHours/YearlyHoursExportBuilder.php b/src/Service/WorkHours/YearlyHoursExportBuilder.php index 2d9f3ae..c1faaa2 100644 --- a/src/Service/WorkHours/YearlyHoursExportBuilder.php +++ b/src/Service/WorkHours/YearlyHoursExportBuilder.php @@ -29,6 +29,7 @@ class YearlyHoursExportBuilder private WorkedHoursCreditPolicy $workedHoursCreditPolicy, private PublicHolidayServiceInterface $publicHolidayService, private HolidayVirtualHoursResolver $holidayVirtualHoursResolver, + private NightHoursCalculator $nightHoursCalculator, ) {} /** @@ -541,14 +542,12 @@ class YearlyHoursExportBuilder ]; $totalMinutes = 0; - $nightMinutes = 0; - foreach ($ranges as [$from, $to]) { $totalMinutes += $this->intervalMinutes($from, $to); - $nightMinutes += $this->nightIntervalMinutes($from, $to); } - $dayMinutes = max(0, $totalMinutes - $nightMinutes); + $nightMinutes = $this->nightHoursCalculator->nightMinutesFromRanges($workHour); + $dayMinutes = max(0, $totalMinutes - $nightMinutes); return new WorkMetrics( dayMinutes: $dayMinutes, @@ -596,35 +595,6 @@ class YearlyHoursExportBuilder return max(0, $end - $start); } - private function nightIntervalMinutes(?string $from, ?string $to): int - { - $interval = $this->resolveInterval($from, $to); - if (null === $interval) { - return 0; - } - - [$start, $end] = $interval; - $windows = [[0, 360], [1260, 1440]]; - $total = 0; - - for ($dayOffset = 0; $dayOffset <= 1; ++$dayOffset) { - $shift = $dayOffset * 1440; - foreach ($windows as [$windowStart, $windowEnd]) { - $total += $this->overlap($start, $end, $windowStart + $shift, $windowEnd + $shift); - } - } - - return $total; - } - - private function overlap(int $startA, int $endA, int $startB, int $endB): int - { - $start = max($startA, $startB); - $end = min($endA, $endB); - - return max(0, $end - $start); - } - private function formatMinutes(int $minutes): string { if (0 === $minutes) { diff --git a/src/State/WorkHourWeeklySummaryProvider.php b/src/State/WorkHourWeeklySummaryProvider.php index 5885c05..ec8cee7 100644 --- a/src/State/WorkHourWeeklySummaryProvider.php +++ b/src/State/WorkHourWeeklySummaryProvider.php @@ -28,6 +28,7 @@ use App\Service\PublicHolidayServiceInterface; use App\Service\WorkHours\AbsenceSegmentsResolver; use App\Service\WorkHours\DailyReferenceMinutesResolver; use App\Service\WorkHours\HolidayVirtualHoursResolver; +use App\Service\WorkHours\NightHoursCalculator; use App\Service\WorkHours\WorkedHoursCreditPolicy; use DateTimeImmutable; use Symfony\Bundle\SecurityBundle\Security; @@ -51,6 +52,7 @@ final readonly class WorkHourWeeklySummaryProvider implements ProviderInterface private HolidayVirtualHoursResolver $holidayVirtualHoursResolver, private PublicHolidayServiceInterface $publicHolidayService, private EmployeeWeekCommentRepository $weekCommentRepository, + private NightHoursCalculator $nightHoursCalculator, ) {} public function provide(Operation $operation, array $uriVariables = [], array $context = []): WorkHourWeeklySummary @@ -433,14 +435,12 @@ final readonly class WorkHourWeeklySummaryProvider implements ProviderInterface ]; $totalMinutes = 0; - $nightMinutes = 0; - foreach ($ranges as [$from, $to]) { $totalMinutes += $this->intervalMinutes($from, $to); - $nightMinutes += $this->nightIntervalMinutes($from, $to); } - $dayMinutes = max(0, $totalMinutes - $nightMinutes); + $nightMinutes = $this->nightHoursCalculator->nightMinutesFromRanges($workHour); + $dayMinutes = max(0, $totalMinutes - $nightMinutes); return new WorkMetrics( dayMinutes: $dayMinutes, @@ -489,37 +489,6 @@ final readonly class WorkHourWeeklySummaryProvider implements ProviderInterface return max(0, $end - $start); } - private function nightIntervalMinutes(?string $from, ?string $to): int - { - $interval = $this->resolveInterval($from, $to); - if (null === $interval) { - return 0; - } - - [$start, $end] = $interval; - // FenĂȘtres de nuit: 00:00-06:00 et 21:00-24:00. - $windows = [[0, 360], [1260, 1440]]; - $total = 0; - - // On projette aussi sur J+1 pour couvrir les shifts qui traversent minuit. - for ($dayOffset = 0; $dayOffset <= 1; ++$dayOffset) { - $shift = $dayOffset * 1440; - foreach ($windows as [$windowStart, $windowEnd]) { - $total += $this->overlap($start, $end, $windowStart + $shift, $windowEnd + $shift); - } - } - - return $total; - } - - private function overlap(int $startA, int $endA, int $startB, int $endB): int - { - $start = max($startA, $startB); - $end = min($endA, $endB); - - return max(0, $end - $start); - } - /** * @param array $contractsByDate */ diff --git a/tests/Service/WorkHours/YearlyHoursDayRowsTest.php b/tests/Service/WorkHours/YearlyHoursDayRowsTest.php index 8138be8..212526c 100644 --- a/tests/Service/WorkHours/YearlyHoursDayRowsTest.php +++ b/tests/Service/WorkHours/YearlyHoursDayRowsTest.php @@ -14,6 +14,7 @@ use App\Service\PublicHolidayServiceInterface; use App\Service\WorkHours\AbsenceSegmentsResolver; use App\Service\WorkHours\DailyReferenceMinutesResolver; use App\Service\WorkHours\HolidayVirtualHoursResolver; +use App\Service\WorkHours\NightHoursCalculator; use App\Service\WorkHours\WorkedHoursCreditPolicy; use App\Service\WorkHours\YearlyHoursExportBuilder; use DateTimeImmutable; @@ -87,6 +88,7 @@ final class YearlyHoursDayRowsTest extends TestCase new WorkedHoursCreditPolicy($contractResolver, new DailyReferenceMinutesResolver()), $holidayService, $virtualResolver, + new NightHoursCalculator(), ); $rows = $builder->buildDayRowsForEmployees([$withContract, $noContract], $date); diff --git a/tests/State/WorkHourWeeklySummaryProviderTest.php b/tests/State/WorkHourWeeklySummaryProviderTest.php index 63ba1de..e5281c2 100644 --- a/tests/State/WorkHourWeeklySummaryProviderTest.php +++ b/tests/State/WorkHourWeeklySummaryProviderTest.php @@ -21,6 +21,7 @@ use App\Service\PublicHolidayServiceInterface; use App\Service\WorkHours\AbsenceSegmentsResolver; use App\Service\WorkHours\DailyReferenceMinutesResolver; use App\Service\WorkHours\HolidayVirtualHoursResolver; +use App\Service\WorkHours\NightHoursCalculator; use App\Service\WorkHours\WorkedHoursCreditPolicy; use App\State\WorkHourWeeklySummaryProvider; use DateTime; @@ -69,6 +70,7 @@ final class WorkHourWeeklySummaryProviderTest extends TestCase $this->buildHolidayResolver(), $this->buildHolidayService(), $this->buildWeekCommentRepoStub(), + new NightHoursCalculator(), ); $this->expectException(AccessDeniedHttpException::class); @@ -133,6 +135,7 @@ final class WorkHourWeeklySummaryProviderTest extends TestCase $this->buildHolidayResolver(), $this->buildHolidayService(), $this->buildWeekCommentRepoStub(), + new NightHoursCalculator(), ); $result = $provider->provide(new Get());