refactor(night) : mutualiser le calcul de nuit via NightHoursCalculator
This commit is contained in:
@@ -29,6 +29,7 @@ class YearlyHoursExportBuilder
|
|||||||
private WorkedHoursCreditPolicy $workedHoursCreditPolicy,
|
private WorkedHoursCreditPolicy $workedHoursCreditPolicy,
|
||||||
private PublicHolidayServiceInterface $publicHolidayService,
|
private PublicHolidayServiceInterface $publicHolidayService,
|
||||||
private HolidayVirtualHoursResolver $holidayVirtualHoursResolver,
|
private HolidayVirtualHoursResolver $holidayVirtualHoursResolver,
|
||||||
|
private NightHoursCalculator $nightHoursCalculator,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -541,13 +542,11 @@ class YearlyHoursExportBuilder
|
|||||||
];
|
];
|
||||||
|
|
||||||
$totalMinutes = 0;
|
$totalMinutes = 0;
|
||||||
$nightMinutes = 0;
|
|
||||||
|
|
||||||
foreach ($ranges as [$from, $to]) {
|
foreach ($ranges as [$from, $to]) {
|
||||||
$totalMinutes += $this->intervalMinutes($from, $to);
|
$totalMinutes += $this->intervalMinutes($from, $to);
|
||||||
$nightMinutes += $this->nightIntervalMinutes($from, $to);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$nightMinutes = $this->nightHoursCalculator->nightMinutesFromRanges($workHour);
|
||||||
$dayMinutes = max(0, $totalMinutes - $nightMinutes);
|
$dayMinutes = max(0, $totalMinutes - $nightMinutes);
|
||||||
|
|
||||||
return new WorkMetrics(
|
return new WorkMetrics(
|
||||||
@@ -596,35 +595,6 @@ class YearlyHoursExportBuilder
|
|||||||
return max(0, $end - $start);
|
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
|
private function formatMinutes(int $minutes): string
|
||||||
{
|
{
|
||||||
if (0 === $minutes) {
|
if (0 === $minutes) {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ use App\Service\PublicHolidayServiceInterface;
|
|||||||
use App\Service\WorkHours\AbsenceSegmentsResolver;
|
use App\Service\WorkHours\AbsenceSegmentsResolver;
|
||||||
use App\Service\WorkHours\DailyReferenceMinutesResolver;
|
use App\Service\WorkHours\DailyReferenceMinutesResolver;
|
||||||
use App\Service\WorkHours\HolidayVirtualHoursResolver;
|
use App\Service\WorkHours\HolidayVirtualHoursResolver;
|
||||||
|
use App\Service\WorkHours\NightHoursCalculator;
|
||||||
use App\Service\WorkHours\WorkedHoursCreditPolicy;
|
use App\Service\WorkHours\WorkedHoursCreditPolicy;
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use Symfony\Bundle\SecurityBundle\Security;
|
use Symfony\Bundle\SecurityBundle\Security;
|
||||||
@@ -51,6 +52,7 @@ final readonly class WorkHourWeeklySummaryProvider implements ProviderInterface
|
|||||||
private HolidayVirtualHoursResolver $holidayVirtualHoursResolver,
|
private HolidayVirtualHoursResolver $holidayVirtualHoursResolver,
|
||||||
private PublicHolidayServiceInterface $publicHolidayService,
|
private PublicHolidayServiceInterface $publicHolidayService,
|
||||||
private EmployeeWeekCommentRepository $weekCommentRepository,
|
private EmployeeWeekCommentRepository $weekCommentRepository,
|
||||||
|
private NightHoursCalculator $nightHoursCalculator,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function provide(Operation $operation, array $uriVariables = [], array $context = []): WorkHourWeeklySummary
|
public function provide(Operation $operation, array $uriVariables = [], array $context = []): WorkHourWeeklySummary
|
||||||
@@ -433,13 +435,11 @@ final readonly class WorkHourWeeklySummaryProvider implements ProviderInterface
|
|||||||
];
|
];
|
||||||
|
|
||||||
$totalMinutes = 0;
|
$totalMinutes = 0;
|
||||||
$nightMinutes = 0;
|
|
||||||
|
|
||||||
foreach ($ranges as [$from, $to]) {
|
foreach ($ranges as [$from, $to]) {
|
||||||
$totalMinutes += $this->intervalMinutes($from, $to);
|
$totalMinutes += $this->intervalMinutes($from, $to);
|
||||||
$nightMinutes += $this->nightIntervalMinutes($from, $to);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$nightMinutes = $this->nightHoursCalculator->nightMinutesFromRanges($workHour);
|
||||||
$dayMinutes = max(0, $totalMinutes - $nightMinutes);
|
$dayMinutes = max(0, $totalMinutes - $nightMinutes);
|
||||||
|
|
||||||
return new WorkMetrics(
|
return new WorkMetrics(
|
||||||
@@ -489,37 +489,6 @@ final readonly class WorkHourWeeklySummaryProvider implements ProviderInterface
|
|||||||
return max(0, $end - $start);
|
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<string, ?Contract> $contractsByDate
|
* @param array<string, ?Contract> $contractsByDate
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use App\Service\PublicHolidayServiceInterface;
|
|||||||
use App\Service\WorkHours\AbsenceSegmentsResolver;
|
use App\Service\WorkHours\AbsenceSegmentsResolver;
|
||||||
use App\Service\WorkHours\DailyReferenceMinutesResolver;
|
use App\Service\WorkHours\DailyReferenceMinutesResolver;
|
||||||
use App\Service\WorkHours\HolidayVirtualHoursResolver;
|
use App\Service\WorkHours\HolidayVirtualHoursResolver;
|
||||||
|
use App\Service\WorkHours\NightHoursCalculator;
|
||||||
use App\Service\WorkHours\WorkedHoursCreditPolicy;
|
use App\Service\WorkHours\WorkedHoursCreditPolicy;
|
||||||
use App\Service\WorkHours\YearlyHoursExportBuilder;
|
use App\Service\WorkHours\YearlyHoursExportBuilder;
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
@@ -87,6 +88,7 @@ final class YearlyHoursDayRowsTest extends TestCase
|
|||||||
new WorkedHoursCreditPolicy($contractResolver, new DailyReferenceMinutesResolver()),
|
new WorkedHoursCreditPolicy($contractResolver, new DailyReferenceMinutesResolver()),
|
||||||
$holidayService,
|
$holidayService,
|
||||||
$virtualResolver,
|
$virtualResolver,
|
||||||
|
new NightHoursCalculator(),
|
||||||
);
|
);
|
||||||
|
|
||||||
$rows = $builder->buildDayRowsForEmployees([$withContract, $noContract], $date);
|
$rows = $builder->buildDayRowsForEmployees([$withContract, $noContract], $date);
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ use App\Service\PublicHolidayServiceInterface;
|
|||||||
use App\Service\WorkHours\AbsenceSegmentsResolver;
|
use App\Service\WorkHours\AbsenceSegmentsResolver;
|
||||||
use App\Service\WorkHours\DailyReferenceMinutesResolver;
|
use App\Service\WorkHours\DailyReferenceMinutesResolver;
|
||||||
use App\Service\WorkHours\HolidayVirtualHoursResolver;
|
use App\Service\WorkHours\HolidayVirtualHoursResolver;
|
||||||
|
use App\Service\WorkHours\NightHoursCalculator;
|
||||||
use App\Service\WorkHours\WorkedHoursCreditPolicy;
|
use App\Service\WorkHours\WorkedHoursCreditPolicy;
|
||||||
use App\State\WorkHourWeeklySummaryProvider;
|
use App\State\WorkHourWeeklySummaryProvider;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
@@ -69,6 +70,7 @@ final class WorkHourWeeklySummaryProviderTest extends TestCase
|
|||||||
$this->buildHolidayResolver(),
|
$this->buildHolidayResolver(),
|
||||||
$this->buildHolidayService(),
|
$this->buildHolidayService(),
|
||||||
$this->buildWeekCommentRepoStub(),
|
$this->buildWeekCommentRepoStub(),
|
||||||
|
new NightHoursCalculator(),
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->expectException(AccessDeniedHttpException::class);
|
$this->expectException(AccessDeniedHttpException::class);
|
||||||
@@ -133,6 +135,7 @@ final class WorkHourWeeklySummaryProviderTest extends TestCase
|
|||||||
$this->buildHolidayResolver(),
|
$this->buildHolidayResolver(),
|
||||||
$this->buildHolidayService(),
|
$this->buildHolidayService(),
|
||||||
$this->buildWeekCommentRepoStub(),
|
$this->buildWeekCommentRepoStub(),
|
||||||
|
new NightHoursCalculator(),
|
||||||
);
|
);
|
||||||
|
|
||||||
$result = $provider->provide(new Get());
|
$result = $provider->provide(new Get());
|
||||||
|
|||||||
Reference in New Issue
Block a user