feat : ajout de la gestion des heures chauffeurs
All checks were successful
Auto Tag Develop / tag (push) Successful in 8s

This commit is contained in:
2026-03-15 19:04:52 +01:00
parent 43957903b0
commit 339d650b41
35 changed files with 2015 additions and 42 deletions

View File

@@ -95,7 +95,8 @@ final readonly class WorkHourBulkUpsertProcessor implements ProcessorInterface
));
}
$isPresenceTracking = TrackingMode::PRESENCE->value === $contract?->getTrackingMode();
$normalized = $this->normalizeEntry($entry, $employeeId, $isPresenceTracking);
$isDriver = $this->contractResolver->resolveIsDriverForEmployeeAndDate($employee, $workDate);
$normalized = $this->normalizeEntry($entry, $employeeId, $isPresenceTracking, $isDriver);
$existing = $existingByEmployeeId[$employeeId] ?? null;
$isAdmin = in_array('ROLE_ADMIN', $user->getRoles(), true);
$isSelf = in_array('ROLE_SELF', $user->getRoles(), true);
@@ -225,11 +226,34 @@ final readonly class WorkHourBulkUpsertProcessor implements ProcessorInterface
* eveningFrom:?string,
* eveningTo:?string,
* isPresentMorning:bool,
* isPresentAfternoon:bool
* isPresentAfternoon:bool,
* dayHoursMinutes:?int,
* nightHoursMinutes:?int,
* hasBreakfast:bool,
* hasLunch:bool,
* hasOvernight:bool
* }
*/
private function normalizeEntry(array $entry, int $employeeId, bool $isPresenceTracking): array
private function normalizeEntry(array $entry, int $employeeId, bool $isPresenceTracking, bool $isDriver): array
{
if ($isDriver) {
return [
'morningFrom' => null,
'morningTo' => null,
'afternoonFrom' => null,
'afternoonTo' => null,
'eveningFrom' => null,
'eveningTo' => null,
'isPresentMorning' => false,
'isPresentAfternoon' => false,
'dayHoursMinutes' => $this->normalizeMinutes($entry['dayHoursMinutes'] ?? null, $employeeId, 'dayHoursMinutes'),
'nightHoursMinutes' => $this->normalizeMinutes($entry['nightHoursMinutes'] ?? null, $employeeId, 'nightHoursMinutes'),
'hasBreakfast' => $this->normalizePresence($entry['hasBreakfast'] ?? false, $employeeId, 'hasBreakfast'),
'hasLunch' => $this->normalizePresence($entry['hasLunch'] ?? false, $employeeId, 'hasLunch'),
'hasOvernight' => $this->normalizePresence($entry['hasOvernight'] ?? false, $employeeId, 'hasOvernight'),
];
}
if ($isPresenceTracking) {
return [
'morningFrom' => null,
@@ -240,6 +264,11 @@ final readonly class WorkHourBulkUpsertProcessor implements ProcessorInterface
'eveningTo' => null,
'isPresentMorning' => $this->normalizePresence($entry['isPresentMorning'] ?? false, $employeeId, 'isPresentMorning'),
'isPresentAfternoon' => $this->normalizePresence($entry['isPresentAfternoon'] ?? false, $employeeId, 'isPresentAfternoon'),
'dayHoursMinutes' => null,
'nightHoursMinutes' => null,
'hasBreakfast' => false,
'hasLunch' => false,
'hasOvernight' => false,
];
}
@@ -254,6 +283,11 @@ final readonly class WorkHourBulkUpsertProcessor implements ProcessorInterface
// même si le contrat résolu ce jour est en suivi horaire.
'isPresentMorning' => $this->normalizePresence($entry['isPresentMorning'] ?? false, $employeeId, 'isPresentMorning'),
'isPresentAfternoon' => $this->normalizePresence($entry['isPresentAfternoon'] ?? false, $employeeId, 'isPresentAfternoon'),
'dayHoursMinutes' => null,
'nightHoursMinutes' => null,
'hasBreakfast' => false,
'hasLunch' => false,
'hasOvernight' => false,
];
}
@@ -283,6 +317,32 @@ final readonly class WorkHourBulkUpsertProcessor implements ProcessorInterface
return $time;
}
private function normalizeMinutes(mixed $value, int $employeeId, string $field): ?int
{
if (null === $value || '' === $value) {
return null;
}
if (!is_int($value) && !is_float($value)) {
throw new UnprocessableEntityHttpException(sprintf(
'Employee %d: %s must be an integer (minutes).',
$employeeId,
$field
));
}
$minutes = (int) $value;
if ($minutes < 0) {
throw new UnprocessableEntityHttpException(sprintf(
'Employee %d: %s must be >= 0.',
$employeeId,
$field
));
}
return $minutes;
}
private function normalizePresence(mixed $value, int $employeeId, string $field): bool
{
if (!is_bool($value)) {
@@ -305,7 +365,12 @@ final readonly class WorkHourBulkUpsertProcessor implements ProcessorInterface
* eveningFrom:?string,
* eveningTo:?string,
* isPresentMorning:bool,
* isPresentAfternoon:bool
* isPresentAfternoon:bool,
* dayHoursMinutes:?int,
* nightHoursMinutes:?int,
* hasBreakfast:bool,
* hasLunch:bool,
* hasOvernight:bool
* } $entry
*/
private function isEntryEmpty(array $entry): bool
@@ -317,7 +382,12 @@ final readonly class WorkHourBulkUpsertProcessor implements ProcessorInterface
&& null === $entry['eveningFrom']
&& null === $entry['eveningTo']
&& false === $entry['isPresentMorning']
&& false === $entry['isPresentAfternoon'];
&& false === $entry['isPresentAfternoon']
&& (null === $entry['dayHoursMinutes'] || 0 === $entry['dayHoursMinutes'])
&& (null === $entry['nightHoursMinutes'] || 0 === $entry['nightHoursMinutes'])
&& false === $entry['hasBreakfast']
&& false === $entry['hasLunch']
&& false === $entry['hasOvernight'];
}
/**
@@ -329,7 +399,12 @@ final readonly class WorkHourBulkUpsertProcessor implements ProcessorInterface
* eveningFrom:?string,
* eveningTo:?string,
* isPresentMorning:bool,
* isPresentAfternoon:bool
* isPresentAfternoon:bool,
* dayHoursMinutes:?int,
* nightHoursMinutes:?int,
* hasBreakfast:bool,
* hasLunch:bool,
* hasOvernight:bool
* } $entry
*/
private function hydrateWorkHour(WorkHour $workHour, array $entry): void
@@ -343,6 +418,11 @@ final readonly class WorkHourBulkUpsertProcessor implements ProcessorInterface
->setEveningTo($entry['eveningTo'])
->setIsPresentMorning($entry['isPresentMorning'])
->setIsPresentAfternoon($entry['isPresentAfternoon'])
->setDayHoursMinutes($entry['dayHoursMinutes'])
->setNightHoursMinutes($entry['nightHoursMinutes'])
->setHasBreakfast($entry['hasBreakfast'])
->setHasLunch($entry['hasLunch'])
->setHasOvernight($entry['hasOvernight'])
// Toute modification invalide la validation chef de site.
->setIsSiteValid(false)
// Toute modification utilisateur repasse la ligne en attente de validation RH.
@@ -359,7 +439,12 @@ final readonly class WorkHourBulkUpsertProcessor implements ProcessorInterface
* eveningFrom:?string,
* eveningTo:?string,
* isPresentMorning:bool,
* isPresentAfternoon:bool
* isPresentAfternoon:bool,
* dayHoursMinutes:?int,
* nightHoursMinutes:?int,
* hasBreakfast:bool,
* hasLunch:bool,
* hasOvernight:bool
* } $entry
*/
private function isSameAsExisting(WorkHour $workHour, array $entry): bool
@@ -371,6 +456,11 @@ final readonly class WorkHourBulkUpsertProcessor implements ProcessorInterface
&& $workHour->getEveningFrom() === $entry['eveningFrom']
&& $workHour->getEveningTo() === $entry['eveningTo']
&& $workHour->getIsPresentMorning() === $entry['isPresentMorning']
&& $workHour->getIsPresentAfternoon() === $entry['isPresentAfternoon'];
&& $workHour->getIsPresentAfternoon() === $entry['isPresentAfternoon']
&& $workHour->getDayHoursMinutes() === $entry['dayHoursMinutes']
&& $workHour->getNightHoursMinutes() === $entry['nightHoursMinutes']
&& $workHour->getHasBreakfast() === $entry['hasBreakfast']
&& $workHour->getHasLunch() === $entry['hasLunch']
&& $workHour->getHasOvernight() === $entry['hasOvernight'];
}
}