Files
SIRH/src/State/AbsencePrintProvider.php
tristan 4d90f2cb42
All checks were successful
Auto Tag Develop / tag (push) Successful in 5s
feat : ajout du nouveau système de contrat et ajout de filtre d'impression
2026-02-26 17:15:13 +01:00

246 lines
8.1 KiB
PHP

<?php
declare(strict_types=1);
namespace App\State;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ProviderInterface;
use App\Enum\ContractNature;
use App\Enum\HalfDay;
use App\Repository\AbsenceRepository;
use App\Repository\EmployeeRepository;
use App\Service\PublicHolidayServiceInterface;
use DateInterval;
use DateTimeImmutable;
use Dompdf\Dompdf;
use Dompdf\Options;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Throwable;
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
class AbsencePrintProvider implements ProviderInterface
{
public function __construct(
private Environment $twig,
private readonly RequestStack $requestStack,
private EmployeeRepository $employeeRepository,
private AbsenceRepository $absenceRepository,
private PublicHolidayServiceInterface $publicHolidayService,
) {}
/**
* @throws SyntaxError
* @throws RuntimeError
* @throws LoaderError
*/
public function provide(Operation $operation, array $uriVariables = [], array $context = []): Response
{
$request = $this->requestStack->getCurrentRequest();
if (!$request) {
return new Response('Missing request.', Response::HTTP_BAD_REQUEST);
}
$from = $request->query->get('from');
$to = $request->query->get('to');
if (!$from || !$to) {
return new Response('Missing from/to query params.', Response::HTTP_BAD_REQUEST);
}
$fromDate = DateTimeImmutable::createFromFormat('Y-m-d', $from);
$toDate = DateTimeImmutable::createFromFormat('Y-m-d', $to);
$siteIds = $this->parseIds($request->query->get('sites'));
$workContractIds = $this->parseIds($request->query->get('workContracts'));
$contractNatures = $this->parseContractNatures($request->query->get('contractNatures'));
$employees = $this->loadEmployees($siteIds, $contractNatures, $workContractIds);
$absences = $this->loadAbsences($fromDate, $toDate, $employees);
$days = $this->buildDays($fromDate, $toDate);
$absenceMap = $this->buildAbsenceMap($absences, $fromDate, $toDate);
$holidayMap = $this->buildHolidayMap($fromDate, $toDate);
$options = new Options();
$options->set('isRemoteEnabled', true);
$dompdf = new Dompdf($options);
$html = $this->twig->render('absence/print.html.twig', [
'from' => $fromDate,
'to' => $toDate,
'days' => $days,
'employees' => $employees,
'absenceMap' => $absenceMap,
'holidayMap' => $holidayMap,
]);
$dompdf->loadHtml($html);
$dompdf->setPaper('A3', 'landscape');
$dompdf->render();
$filename = sprintf(
'absences_du_%s_au_%s.pdf',
$fromDate->format('d-m-Y'),
$toDate->format('d-m-Y')
);
return new Response($dompdf->output(), Response::HTTP_OK, [
'Content-Type' => 'application/pdf',
'Content-Disposition' => 'inline; filename="'.$filename.'"',
]);
}
private function parseIds(?string $value): array
{
if (null === $value || '' === trim($value)) {
return [];
}
$ids = [];
foreach (explode(',', $value) as $part) {
$id = (int) trim($part);
if ($id > 0) {
$ids[] = $id;
}
}
return array_values(array_unique($ids));
}
private function loadEmployees(array $siteIds, array $contractNatures, array $workContractIds): array
{
$employees = $this->employeeRepository->findForPrintBySiteIds($siteIds);
return array_values(array_filter($employees, static function ($employee) use ($contractNatures, $workContractIds): bool {
$employeeNature = (string) $employee->getCurrentContractNature();
$employeeContractId = $employee->getContract()?->getId();
$natureMatches = [] === $contractNatures || in_array($employeeNature, $contractNatures, true);
$contractMatches = [] === $workContractIds || (null !== $employeeContractId && in_array($employeeContractId, $workContractIds, true));
return $natureMatches && $contractMatches;
}));
}
private function loadAbsences(DateTimeImmutable $from, DateTimeImmutable $to, array $employees): array
{
return $this->absenceRepository->findForPrint($from, $to, $employees);
}
private function buildDays(DateTimeImmutable $from, DateTimeImmutable $to): array
{
$days = [];
$current = $from;
while ($current <= $to) {
$days[] = [
'date' => $current->format('Y-m-d'),
'label' => $current->format('d'),
];
$current = $current->add(new DateInterval('P1D'));
}
return $days;
}
private function buildAbsenceMap(array $absences, DateTimeImmutable $from, DateTimeImmutable $to): array
{
$map = [];
foreach ($absences as $absence) {
$employeeId = $absence->getEmployee()?->getId();
$type = $absence->getType();
if (!$employeeId || !$type) {
continue;
}
$absenceStart = DateTimeImmutable::createFromInterface($absence->getStartDate());
$absenceEnd = DateTimeImmutable::createFromInterface($absence->getEndDate());
$startHalf = $absence->getStartHalf();
$endHalf = $absence->getEndHalf();
$start = max($absenceStart, $from);
$end = min($absenceEnd, $to);
$current = $start;
while ($current <= $end) {
$dateKey = $current->format('Y-m-d');
$isSameDay = $absenceStart->format('Y-m-d') === $absenceEnd->format('Y-m-d');
$isStartDay = $current->format('Y-m-d') === $absenceStart->format('Y-m-d');
$isEndDay = $current->format('Y-m-d') === $absenceEnd->format('Y-m-d');
$halfLabel = null;
if ($isSameDay) {
if ($startHalf === $endHalf) {
$halfLabel = $startHalf->value;
}
} else {
if ($isStartDay && HalfDay::PM === $startHalf) {
$halfLabel = 'PM';
}
if ($isEndDay && HalfDay::AM === $endHalf) {
$halfLabel = 'AM';
}
}
$map[$employeeId][$dateKey] = [
'code' => (string) $type->getCode(),
'color' => (string) $type->getColor(),
'half' => null !== $halfLabel,
'halfLabel' => $halfLabel,
];
$current = $current->add(new DateInterval('P1D'));
}
}
return $map;
}
private function buildHolidayMap(DateTimeImmutable $from, DateTimeImmutable $to): array
{
$map = [];
$startYear = (int) $from->format('Y');
$endYear = (int) $to->format('Y');
try {
for ($year = $startYear; $year <= $endYear; ++$year) {
$holidays = $this->publicHolidayService->getHolidaysDayByYears('metropole', (string) $year);
foreach ($holidays as $date => $label) {
$map[$date] = (string) $label;
}
}
} catch (Throwable) {
return [];
}
return $map;
}
/**
* @return list<string>
*/
private function parseContractNatures(?string $value): array
{
if (null === $value || '' === trim($value)) {
return [];
}
$values = [];
foreach (explode(',', $value) as $part) {
$nature = strtoupper(trim($part));
if (null !== ContractNature::tryFrom($nature)) {
$values[] = $nature;
}
}
return array_values(array_unique($values));
}
}